Neodroid  0.2.0
Machine Learning Environment Prototyping Tool
AbstractPrototypingEnvironment.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Linq;
13 using UnityEngine;
14 using Object = System.Object;
15 
16 namespace droid.Runtime.Environments {
22  //, IResetable
23 
24  {
30  public override EnvironmentState ReactAndCollectState(Reaction reaction) {
31  this.React(reaction);
32 
33  return this.CollectState();
34  }
35 
41  public void Terminate(string reason = "None") {
42  lock (this._Reaction_Lock) {
43  if (this._Terminable) {
44  #if NEODROID_DEBUG
45  if (this.Debugging) {
46  Debug.LogWarning($"Environment {this.Identifier} as terminated because {reason}");
47  }
48  #endif
49 
50  this._Terminated = true;
51  this._LastTermination_Reason = reason;
52  }
53  }
54  }
55 
59  public override void Tick() {
60  if (this._Resetting) {
61  if (this._reset_i >= this._Simulation_Manager.SimulatorConfiguration.ResetIterations) {
62  this._Resetting = false;
63  this._reset_i = 0;
64  this.UpdateConfigurableValues();
65  this.UpdateObserversData();
66  } else {
67  this.EnvironmentReset();
68  this._reset_i += 1;
69  }
70 
71  #if NEODROID_DEBUG
72  if (this.Debugging) {
73  Debug.Log($"Reset {this._reset_i}/{this._Simulation_Manager.SimulatorConfiguration.ResetIterations}");
74  }
75  #endif
76  } else {
77  if (this.update_observations_with_every_tick) {
78  this.UpdateObserversData();
79  }
80  }
81 
82  #if NEODROID_DEBUG
83  if (this.Debugging) {
84  Debug.Log("Tick");
85  }
86  #endif
87  }
88 
91  protected void UpdateObserversData() {
92  foreach (var obs in this.Observers.Values) {
93  obs?.UpdateObservation();
94  }
95  }
96 
99  protected void UpdateConfigurableValues() {
100  foreach (var con in this.Configurables.Values) {
101  con?.Tick();
102  con?.UpdateCurrentConfiguration();
103  }
104  }
105 
106  #region PrivateMembers
107 
110  Vector3[] _reset_positions;
111 
114  Quaternion[] _reset_rotations;
115 
118  GameObject[] _tracked_game_objects;
119 
122  Vector3[] _reset_velocities;
123 
126  Vector3[] _reset_angulars;
127 
130  protected Rigidbody[] _Tracked_Rigid_Bodies;
131 
134  protected Transform[] _Poses;
135 
138  Pose[] _received_poses;
139 
142  Body[] _received_bodies;
143 
146  Configuration[] _received_configurations;
147 
150  Animation[] _animations;
151 
154  float[] _reset_animation_times;
155 
156  #endregion
157 
158  #region Events
159 
162  public event Action PreStepEvent;
163 
167  public event Action StepEvent;
168 
172  public event Action PostStepEvent;
173 
174  #endregion
175 
176  #region Fields
177 
180  [Header("References", order = 20)]
181  [SerializeField]
183 
186  [Header("General", order = 30)]
187  [SerializeField]
188  protected Transform _coordinate_reference_point;
189 
192  [SerializeField]
193  protected bool _track_only_children = true;
194 
197  [SerializeField]
198  protected CoordinateSystem _coordinate_system = CoordinateSystem.Local_coordinates_;
199 
202  [Header("(Optional)", order = 80)]
203  [SerializeField]
205 
208  protected Object _Reaction_Lock = new Object();
209 
213  [SerializeField]
214  protected int _reset_i;
215 
219  protected WaitForFixedUpdate _Wait_For_Fixed_Update = new WaitForFixedUpdate();
220 
224  protected List<float> _Observables = new List<float>();
225 
229  protected List<ActuatorMotion> _Sample_Motions = new List<ActuatorMotion>();
230 
234  [SerializeField]
235  protected bool update_observations_with_every_tick = true;
236 
237  #endregion
238 
239  #region Private Methods
240 
243  void SaveInitialPoses() {
244  var ignored_layer = LayerMask.NameToLayer("IgnoredByNeodroid");
245  if (this._track_only_children) {
246  this._tracked_game_objects =
247  NeodroidUtilities.RecursiveChildGameObjectsExceptLayer(this.transform, ignored_layer);
248  } else {
249  this._tracked_game_objects = NeodroidUtilities.FindAllGameObjectsExceptLayer(ignored_layer);
250  }
251 
252  var length = this._tracked_game_objects.Length;
253 
254  this._reset_positions = new Vector3[length];
255  this._reset_rotations = new Quaternion[length];
256  this._Poses = new Transform[length];
257  for (var i = 0; i < length; i++) {
258  var go = this._tracked_game_objects[i];
259  var trans = go.transform;
260  this._reset_positions[i] = trans.position;
261  this._reset_rotations[i] = trans.rotation;
262  this._Poses[i] = trans;
263  var maybe_joint = go.GetComponent<Joint>();
264  if (maybe_joint != null) {
265  var maybe_joint_fix = maybe_joint.GetComponent<JointFix>();
266  if (maybe_joint_fix == null) {
267  // ReSharper disable once RedundantAssignment
268  maybe_joint_fix = maybe_joint.gameObject.AddComponent<JointFix>();
269  }
270  #if NEODROID_DEBUG
271  if (this.Debugging) {
272  Debug.Log($"Added a JointFix component to {maybe_joint_fix.name}");
273  }
274  #endif
275  }
276  }
277  }
278 
281  void SaveInitialBodies() {
282  /*var body_list = new List<Rigidbody>();
283  foreach (var go in this._tracked_game_objects) {
284  if (go != null) {
285  var body = go.GetComponent<Rigidbody>();
286  if (body)
287  body_list.Add(body);
288  }
289  }
290  this._bodies = body_list.ToArray();
291  */ //Should be equalvalent to the line below, but kept as a reference in case of confusion
292 
293  this._Tracked_Rigid_Bodies = this._tracked_game_objects.Where(go => go != null)
294  .Select(go => go.GetComponent<Rigidbody>()).Where(body => body)
295  .ToArray();
296 
297  this._reset_velocities = new Vector3[this._Tracked_Rigid_Bodies.Length];
298  this._reset_angulars = new Vector3[this._Tracked_Rigid_Bodies.Length];
299  for (var i = 0; i < this._Tracked_Rigid_Bodies.Length; i++) {
300  this._reset_velocities[i] = this._Tracked_Rigid_Bodies[i].velocity;
301  this._reset_angulars[i] = this._Tracked_Rigid_Bodies[i].angularVelocity;
302  }
303  }
304 
307  void SaveInitialAnimations() {
308  this._animations = this._tracked_game_objects.Where(go => go != null)
309  .Select(go => go.GetComponent<Animation>()).Where(anim => anim).ToArray();
310  this._reset_animation_times = new float[this._animations.Length];
311  for (var i = 0; i < this._animations.Length; i++) {
312  if (this._animations[i]) {
313  if (this._animations[i].clip) {
314  this._reset_animation_times[i] =
315  this._animations[i].CrossFadeQueued(this._animations[i].clip.name)
316  .time; //TODO: IS NOT USED AS RIGHT NOW and should use animations clips instead the legacy "clip.name".
317  //TODO: DOES NOT WORK
318  }
319  }
320  }
321  }
322 
326  protected override void PreSetup() {
327  if (this._objective_function == null) {
328  this._objective_function = this.GetComponent<ObjectiveFunction>();
329  }
330 
331  if (!this.PlayableArea) {
332  this.PlayableArea = this.GetComponent<BoundingBox>();
333  }
334 
335  #if NEODROID_DEBUG
336  if (this.Debugging) {
337  Debug.Log("Setting up");
338  }
339  #endif
340 
341  if (this._tracked_game_objects == null || this._tracked_game_objects.Length == 0) {
342  this.SaveInitialPoses();
343  this.SaveInitialAnimations();
344  this.StartCoroutine(this.SaveInitialBodiesIe());
345  }
346 
347  #if NEODROID_DEBUG
348  if (this.Debugging) {
349  Debug.Log("Setup done");
350  }
351  #endif
352 
353  foreach (var configurable in this.Configurables.Values) {
354  configurable?.PostEnvironmentSetup();
355  }
356  }
357 
361  IEnumerator SaveInitialBodiesIe() {
362  yield return this._Wait_For_Fixed_Update;
363  this.SaveInitialBodies();
364  }
365 
369  void Step(Reaction reaction) {
370  lock (this._Reaction_Lock) {
371  this.PreStepEvent?.Invoke();
372 
373  if (reaction.Parameters.EpisodeCount) {
374  this.CurrentFrameNumber++;
375  } else {
376  #if NEODROID_DEBUG
377  if (this.Debugging) {
378  Debug.LogWarning("Step did not count towards CurrentFrameNumber");
379  }
380  #endif
381  }
382 
383  this.InnerStep(reaction);
384 
385  this.StepEvent?.Invoke();
386 
387  this.UpdateObserversData();
388  }
389  }
390 
396  public override void React(Reaction reaction) {
397  lock (this._Reaction_Lock) {
398  this.LastReaction = reaction;
399  this._Terminable = reaction.Parameters.Terminable;
400 
401  if (reaction.Parameters.IsExternal) {
402  this._received_configurations = reaction.Configurations;
403 
404  if (!this._ReplyWithDescriptionThisStep) {
405  this._ReplyWithDescriptionThisStep = reaction.Parameters.Describe;
406  }
407 
408  this._Configure = reaction.Parameters.Configure;
409  if (this._Configure && reaction.Unobservables != null) {
410  this._received_poses = reaction.Unobservables.Poses;
411  this._received_bodies = reaction.Unobservables.Bodies;
412  }
413  }
414 
415  this.SendToDisplayers(reaction);
416 
417  if (reaction.Parameters.Reset) {
418  this.Terminate($"{(reaction.Parameters.IsExternal ? "External" : "Internal")} reaction caused a reset");
419  this._Resetting = true;
420  } else if (reaction.Parameters.Step) {
421  #if NEODROID_DEBUG
422  if (this.Debugging) {
423  Debug.Log($"Stepping in environment({this.Identifier})");
424  }
425  #endif
426  this.Step(reaction);
427  }
428  }
429  }
430 
434  public override void PostStep() {
435  this.PostStepEvent?.Invoke();
436  if (this._Configure) {
437  #if NEODROID_DEBUG
438  if (this.Debugging) {
439  Debug.Log("Configuring");
440  }
441  #endif
442  this._Configure = false;
443  this.Reconfigure();
444  }
445 
446  if (!this._Simulation_Manager.IsSyncingEnvironments) {
447  this._ReplyWithDescriptionThisStep = false;
448  }
449  }
450 
453  public override void EnvironmentReset() {
454  this._Lastest_Reset_Time = Time.time;
455  this.CurrentFrameNumber = 0;
456  this._objective_function?.EnvironmentReset();
457 
458  ResetEnvironmentPoses(ref this._tracked_game_objects,
459  ref this._reset_positions,
460  ref this._reset_rotations,
461  this._Simulation_Manager.SimulatorConfiguration.ResetIterations);
462  #if NEODROID_DEBUG
463  ResetEnvironmentBodies(ref this._Tracked_Rigid_Bodies,
464  ref this._reset_velocities,
465  ref this._reset_angulars,
466  this.Debugging);
467  #else
468  ResetEnvironmentBodies(ref this._tracked_rigid_bodies,
469  ref this._reset_velocities,
470  ref this._reset_angulars);
471  #endif
472 
473  this.ResetRegisteredObjects();
474  this.Reconfigure();
475 
476  #if NEODROID_DEBUG
477  if (this.Debugging) {
478  Debug.Log($"Reset called on environment {this.Identifier}");
479  }
480  #endif
481 
482  this._Terminated = false;
483  }
484 
487  protected void ResetRegisteredObjects() {
488  #if NEODROID_DEBUG
489  if (this.Debugging) {
490  Debug.Log("Resetting registered objects");
491  }
492  #endif
493 
494  foreach (var configurable in this.Configurables.Values) {
495  configurable?.EnvironmentReset();
496  }
497 
498  foreach (var resetable in this.Listeners.Values) {
499  resetable?.EnvironmentReset();
500  }
501 
502  this.InnerResetRegisteredObjects();
503 
504  foreach (var observer in this.Observers.Values) {
505  observer?.EnvironmentReset();
506  }
507  }
508 
511  protected void Reconfigure() {
512  if (this._received_poses != null) {
513  var positions = new Vector3[this._received_poses.Length];
514  var rotations = new Quaternion[this._received_poses.Length];
515  for (var i = 0; i < this._received_poses.Length; i++) {
516  positions[i] = this._received_poses[i].position;
517  rotations[i] = this._received_poses[i].rotation;
518  }
519 
520  ResetEnvironmentPoses(ref this._tracked_game_objects,
521  ref positions,
522  ref rotations,
523  this._Simulation_Manager.SimulatorConfiguration.ResetIterations);
524  }
525 
526  if (this._received_bodies != null) {
527  var velocities = new Vector3[this._received_bodies.Length];
528  var angulars = new Vector3[this._received_bodies.Length];
529  for (var i = 0; i < this._received_bodies.Length; i++) {
530  velocities[i] = this._received_bodies[i].Velocity;
531  angulars[i] = this._received_bodies[i].AngularVelocity;
532  }
533 
534  ResetEnvironmentBodies(ref this._Tracked_Rigid_Bodies, ref velocities, ref angulars);
535  }
536 
537  if (this._received_configurations != null) {
538  #if NEODROID_DEBUG
539  if (this.Debugging) {
540  Debug.Log($"Configuration length: {this._received_configurations.Length}");
541  }
542  #endif
543  foreach (var configuration in this._received_configurations) {
544  #if NEODROID_DEBUG
545  if (this.Debugging) {
546  Debug.Log("Configuring configurable with the specified name: " + configuration.ConfigurableName);
547  }
548  #endif
549  if (this.Configurables.ContainsKey(configuration.ConfigurableName)) {
550  this.Configurables[configuration.ConfigurableName].ApplyConfiguration(configuration);
551  } else {
552  #if NEODROID_DEBUG
553  if (this.Debugging) {
554  Debug.Log($"Could find not configurable with the specified name: {configuration.ConfigurableName}");
555  }
556  #endif
557  }
558  }
559  } else {
560  #if NEODROID_DEBUG
561  if (this.Debugging) {
562  Debug.Log("Has no received_configurations");
563  }
564  #endif
565  }
566 
567  this.UpdateConfigurableValues();
568  this.UpdateObserversData();
569  }
570 
574  void SendToDisplayers(Reaction reaction) {
575  if (reaction.Displayables != null && reaction.Displayables.Length > 0) {
576  foreach (var displayable in reaction.Displayables) {
577  #if NEODROID_DEBUG
578  if (this.Debugging) {
579  Debug.Log("Applying " + displayable + " To " + this.name + "'s displayers");
580  }
581  #endif
582  var displayable_name = displayable.DisplayableName;
583  if (this.Displayers.ContainsKey(displayable_name) && this.Displayers[displayable_name] != null) {
584  var v = displayable.DisplayableValue;
585  this.Displayers[displayable_name].Display(v);
586  } else {
587  #if NEODROID_DEBUG
588  if (this.Debugging) {
589  Debug.Log("Could find not displayer with the specified name: " + displayable_name);
590  }
591  #endif
592  }
593  }
594  }
595  }
596 
597  #endregion
598 
599  #region EnvironmentStateSetters
600 
607  static void ResetEnvironmentPoses(ref GameObject[] child_game_objects,
608  ref Vector3[] positions,
609  ref Quaternion[] rotations,
610  int iterations = 1) {
611  for (var it = 1; it <= iterations; it++) {
612  for (var i = 0; i < child_game_objects.Length; i++) {
613  if (child_game_objects[i] != null && i < positions.Length && i < rotations.Length) {
614  var rigid_body = child_game_objects[i].GetComponent<Rigidbody>();
615  if (rigid_body) {
616  rigid_body.Sleep();
617  }
618 
619  child_game_objects[i].transform.position = positions[i];
620  child_game_objects[i].transform.rotation = rotations[i];
621  if (rigid_body) {
622  rigid_body.WakeUp();
623  }
624 
625  var joint_fix = child_game_objects[i].GetComponent<JointFix>();
626  if (joint_fix) {
627  joint_fix.Reset();
628  }
629 
630  var anim = child_game_objects[i].GetComponent<Animation>();
631  if (anim) {
632  anim.Rewind();
633  anim.Play();
634  anim.Sample();
635  anim.Stop();
636  }
637  }
638  }
639  }
640  }
641 
648  static void ResetEnvironmentBodies(ref Rigidbody[] bodies,
649  ref Vector3[] velocities,
650  ref Vector3[] angulars,
651  bool debugging = false) {
652  if (bodies != null && bodies.Length > 0) {
653  for (var i = 0; i < bodies.Length; i++) {
654  if (i < bodies.Length && bodies[i] != null && i < velocities.Length && i < angulars.Length) {
655  #if NEODROID_DEBUG
656  if (debugging) {
657  Debug.Log($"Setting {bodies[i].name}, velocity to {velocities[i]} and angular velocity to {angulars[i]}");
658  }
659 
660  #endif
661 
662  bodies[i].Sleep();
663  bodies[i].velocity = velocities[i];
664  bodies[i].angularVelocity = angulars[i];
665  bodies[i].WakeUp();
666  }
667  }
668  }
669  }
670 
671  #endregion
672 
673  #region Transformations
674 
679  public Vector3 TransformPoint(Vector3 point) {
680  switch (this._coordinate_system) {
681  case CoordinateSystem.Relative_to_reference_point_ when this._coordinate_reference_point:
682  return this._coordinate_reference_point.transform.InverseTransformPoint(point);
683  case CoordinateSystem.Local_coordinates_:
684  return this.transform.InverseTransformPoint(point);
685  //return point - this.transform.position;
686  default:
687  #if NEODROID_DEBUG
688  if (this.Debugging) {
689  Debug.Log("Defaulting TransformPoint");
690  }
691  #endif
692  return point;
693  }
694  }
695 
696  public void TransformPoint(ref Vector3 point) {
697  switch (this._coordinate_system) {
698  case CoordinateSystem.Relative_to_reference_point_ when this._coordinate_reference_point:
699  point = this._coordinate_reference_point.transform.InverseTransformPoint(point);
700  break;
701  case CoordinateSystem.Local_coordinates_:
702  //point = point - this.transform.position;
703  point = this.transform.InverseTransformPoint(point);
704  break;
705  default:
706  #if NEODROID_DEBUG
707  if (this.Debugging) {
708  Debug.Log("Defaulting TransformPoint");
709  }
710  #endif
711  break;
712  }
713  }
714 
719  public Vector3 InverseTransformPoint(Vector3 point) {
720  switch (this._coordinate_system) {
721  case CoordinateSystem.Relative_to_reference_point_ when this._coordinate_reference_point:
722  return this._coordinate_reference_point.transform.TransformPoint(point);
723  case CoordinateSystem.Local_coordinates_:
724  //return point - this.transform.position;
725  return this.transform.TransformPoint(point);
726  default:
727  #if NEODROID_DEBUG
728  if (this.Debugging) {
729  Debug.Log("Defaulting InverseTransformPoint");
730  }
731  #endif
732  return point;
733  }
734  }
735 
740  public void InverseTransformPoint(ref Vector3 point) {
741  switch (this._coordinate_system) {
742  case CoordinateSystem.Relative_to_reference_point_ when this._coordinate_reference_point:
743  point = this._coordinate_reference_point.transform.TransformPoint(point);
744  break;
745  case CoordinateSystem.Local_coordinates_:
746  //point = point - this.transform.position;
747  point = this.transform.TransformPoint(point);
748  break;
749  default:
750  #if NEODROID_DEBUG
751  if (this.Debugging) {
752  Debug.Log("Defaulting InverseTransformPoint");
753  }
754  #endif
755  break;
756  }
757  }
758 
763  public Vector3 TransformDirection(Vector3 direction) {
764  switch (this._coordinate_system) {
765  case CoordinateSystem.Relative_to_reference_point_ when this._coordinate_reference_point:
766  return this._coordinate_reference_point.transform.InverseTransformDirection(direction);
767  case CoordinateSystem.Local_coordinates_:
768  return this.transform.InverseTransformDirection(direction);
769  default:
770  #if NEODROID_DEBUG
771  if (this.Debugging) {
772  Debug.Log("Defaulting TransformDirection");
773  }
774  #endif
775  return direction;
776  }
777  }
778 
783  public void TransformDirection(ref Vector3 direction) {
784  switch (this._coordinate_system) {
785  case CoordinateSystem.Relative_to_reference_point_ when this._coordinate_reference_point:
786  direction = this._coordinate_reference_point.transform.InverseTransformDirection(direction);
787  break;
788  case CoordinateSystem.Local_coordinates_:
789  direction = this.transform.InverseTransformDirection(direction);
790  break;
791  case CoordinateSystem.Global_coordinates_:
792  default:
793  #if NEODROID_DEBUG
794  if (this.Debugging) {
795  Debug.Log("Defaulting TransformDirection");
796  }
797  #endif
798  break;
799  }
800  }
801 
806  public Vector3 InverseTransformDirection(Vector3 direction) {
807  switch (this._coordinate_system) {
808  case CoordinateSystem.Relative_to_reference_point_ when this._coordinate_reference_point:
809  return this._coordinate_reference_point.transform.TransformDirection(direction);
810  case CoordinateSystem.Local_coordinates_:
811  return this.transform.TransformDirection(direction);
812 
813  default:
814  #if NEODROID_DEBUG
815  if (this.Debugging) {
816  Debug.Log("Defaulting InverseTransformDirection");
817  }
818  #endif
819  return direction;
820  }
821  }
822 
823  public void InverseTransformDirection(ref Vector3 direction) {
824  switch (this._coordinate_system) {
825  case CoordinateSystem.Relative_to_reference_point_ when this._coordinate_reference_point:
826  direction = this._coordinate_reference_point.transform.TransformDirection(direction);
827  break;
828  case CoordinateSystem.Local_coordinates_:
829  direction = this.transform.TransformDirection(direction);
830  break;
831  default:
832  #if NEODROID_DEBUG
833  if (this.Debugging) {
834  Debug.Log("Defaulting InverseTransformDirection");
835  }
836  #endif
837  break;
838  }
839  }
840 
845  public Quaternion TransformRotation(Quaternion quaternion) {
846  if (this._coordinate_system == CoordinateSystem.Relative_to_reference_point_) {
847  if (this._coordinate_reference_point) {
848  return Quaternion.Inverse(this._coordinate_reference_point.rotation) * quaternion;
849  }
850 
851  //Quaternion.Euler(this._coordinate_reference_point.transform.TransformDirection(quaternion.forward));
852  } else if (this._coordinate_system == CoordinateSystem.Local_coordinates_) {
853  if (this._coordinate_reference_point) {
854  return Quaternion.Inverse(this.Transform.rotation) * quaternion;
855  }
856  }
857 
858  return quaternion;
859  }
860 
865  public void TransformRotation(ref Quaternion quaternion) {
866  if (this._coordinate_system == CoordinateSystem.Relative_to_reference_point_) {
867  if (this._coordinate_reference_point) {
868  quaternion = Quaternion.Inverse(this._coordinate_reference_point.rotation) * quaternion;
869  }
870 
871  //Quaternion.Euler(this._coordinate_reference_point.transform.TransformDirection(quaternion.forward));
872  } else if (this._coordinate_system == CoordinateSystem.Local_coordinates_) {
873  if (this._coordinate_reference_point) {
874  quaternion = Quaternion.Inverse(this.Transform.rotation) * quaternion;
875  }
876  }
877  }
878 
879  public Quaternion InverseTransformRotation(Quaternion quaternion) {
880  if (this._coordinate_system == CoordinateSystem.Relative_to_reference_point_) {
881  if (this._coordinate_reference_point) {
882  return this._coordinate_reference_point.rotation * quaternion;
883  }
884 
885  //Quaternion.Euler(this._coordinate_reference_point.transform.TransformDirection(quaternion.forward));
886  } else if (this._coordinate_system == CoordinateSystem.Local_coordinates_) {
887  if (this._coordinate_reference_point) {
888  return this.Transform.rotation * quaternion;
889  }
890  }
891 
892  return quaternion;
893  }
894 
895  public void InverseTransformRotation(ref Quaternion quaternion) {
896  if (this._coordinate_system == CoordinateSystem.Relative_to_reference_point_) {
897  if (this._coordinate_reference_point) {
898  quaternion = this._coordinate_reference_point.rotation * quaternion;
899  } else if (this._coordinate_system == CoordinateSystem.Local_coordinates_) {
900  if (this._coordinate_reference_point) {
901  quaternion = this.Transform.rotation * quaternion;
902  }
903  }
904 
905  //Quaternion.Euler(this._coordinate_reference_point.transform.TransformDirection(quaternion.forward));
906  }
907  }
908 
909  #endregion
910 
911  #region Getters
912 
915  public Dictionary<string, IDisplayer> Displayers { get; } = new Dictionary<string, IDisplayer>();
916 
919  public Dictionary<string, IConfigurable> Configurables { get; } = new Dictionary<string, IConfigurable>();
920 
923  public SortedDictionary<string, IObserver> Observers { get; } = new SortedDictionary<string, IObserver>();
924 
927  public Dictionary<string, IEnvironmentListener> Listeners { get; } =
928  new Dictionary<string, IEnvironmentListener>();
929 
933  public override string PrototypingTypeName { get { return "PrototypingEnvironment"; } }
934 
938  get { return this._objective_function; }
939  set { this._objective_function = (ObjectiveFunction)value; }
940  }
941 
944  public Transform Transform { get { return this.transform; } }
945 
948  public BoundingBox PlayableArea {
949  get { return this._playable_area; }
950  set { this._playable_area = value; }
951  }
952 
955  public Transform CoordinateReferencePoint {
956  get { return this._coordinate_reference_point; }
957  set { this._coordinate_reference_point = value; }
958  }
959 
963  get { return this._coordinate_system; }
964  set { this._coordinate_system = value; }
965  }
966 
967  #endregion
968 
969  #region Registration
970 
974  public void Register(IDisplayer displayer) { this.Register(displayer, displayer.Identifier); }
975 
981  public void Register(IDisplayer obj, string identifier) {
982  if (!this.Displayers.ContainsKey(identifier)) {
983  #if NEODROID_DEBUG
984  if (this.Debugging) {
985  Debug.Log($"Environment {this.name} has registered displayer {identifier}");
986  }
987  #endif
988  this.Displayers.Add(identifier, obj);
989  } else {
990  Debug.LogWarning($"WARNING! Please check for duplicates, Environment {this.name} already has displayer {identifier} registered");
991  }
992  }
993 
998  public void Register(IObserver observer) { this.Register(observer, observer.Identifier); }
999 
1006  public void Register(IObserver observer, string identifier) {
1007  if (!this.Observers.ContainsKey(identifier)) {
1008  #if NEODROID_DEBUG
1009  if (this.Debugging) {
1010  Debug.Log($"Environment {this.name} has registered observer {identifier}");
1011  }
1012  #endif
1013 
1014  this.Observers.Add(identifier, observer);
1015  } else {
1016  Debug.LogWarning($"WARNING! Please check for duplicates, Environment {this.name} already has observer {identifier} registered");
1017  }
1018  }
1019 
1024  public void Register(IConfigurable configurable) { this.Register(configurable, configurable.Identifier); }
1025 
1031  public void Register(IConfigurable configurable, string identifier) {
1032  if (!this.Configurables.ContainsKey(identifier)) {
1033  #if NEODROID_DEBUG
1034  if (this.Debugging) {
1035  Debug.Log($"Environment {this.name} has registered configurable {identifier}");
1036  }
1037  #endif
1038 
1039  this.Configurables.Add(identifier, configurable);
1040  } else {
1041  Debug.LogWarning($"WARNING! Please check for duplicates, Environment {this.name} already has configurable {identifier} registered");
1042  }
1043  }
1044 
1049  public void Register(IEnvironmentListener environment_listener) {
1050  this.Register(environment_listener, environment_listener.Identifier);
1051  }
1052 
1058  public void Register(IEnvironmentListener environment_listener, string identifier) {
1059  if (!this.Listeners.ContainsKey(identifier)) {
1060  #if NEODROID_DEBUG
1061  if (this.Debugging) {
1062  Debug.Log($"Environment {this.name} has registered resetable {identifier}");
1063  }
1064  #endif
1065  this.Listeners.Add(identifier, environment_listener);
1066  } else {
1067  Debug.LogWarning($"WARNING! Please check for duplicates, Environment {this.name} already has resetable {identifier} registered");
1068  }
1069  }
1070 
1074  public void UnRegister(IObserver observer) { this.UnRegister(observer, observer.Identifier); }
1075 
1081  public void UnRegister(IObserver t, string identifier) {
1082  if (this.Observers.ContainsKey(identifier)) {
1083  #if NEODROID_DEBUG
1084  if (this.Debugging) {
1085  Debug.Log($"Environment {this.name} unregistered observer {identifier}");
1086  }
1087  #endif
1088  this.Observers.Remove(identifier);
1089  }
1090  }
1091 
1095  public void UnRegister(IConfigurable configurable) {
1096  this.UnRegister(configurable, configurable.Identifier);
1097  }
1098 
1104  public void UnRegister(IConfigurable t, string identifier) {
1105  if (this.Configurables.ContainsKey(identifier)) {
1106  #if NEODROID_DEBUG
1107  if (this.Debugging) {
1108  Debug.Log($"Environment {this.name} unregistered configurable {identifier}");
1109  }
1110  #endif
1111  this.Configurables.Remove(identifier);
1112  }
1113  }
1114 
1118  public void UnRegister(IDisplayer displayer) { this.UnRegister(displayer, displayer.Identifier); }
1119 
1125  public void UnRegister(IDisplayer t, string identifier) {
1126  if (this.Displayers.ContainsKey(identifier)) {
1127  #if NEODROID_DEBUG
1128  if (this.Debugging) {
1129  Debug.Log($"Environment {this.name} unregistered configurable {identifier}");
1130  }
1131  #endif
1132  this.Displayers.Remove(identifier);
1133  }
1134  }
1135 
1139  public void UnRegister(IEnvironmentListener environment_listener) {
1140  this.UnRegister(environment_listener, environment_listener.Identifier);
1141  }
1142 
1148  public void UnRegister(IEnvironmentListener t, string identifier) {
1149  if (this.Listeners.ContainsKey(identifier)) {
1150  #if NEODROID_DEBUG
1151  if (this.Debugging) {
1152  Debug.Log($"Environment {this.name} unregistered resetable {identifier}");
1153  }
1154  #endif
1155  this.Listeners.Remove(identifier);
1156  }
1157  }
1158 
1159  #endregion
1160 
1164  protected abstract void InnerStep(Reaction reaction);
1165 
1169  protected abstract void InnerResetRegisteredObjects();
1170  }
1171 }
void Terminate(string reason="None")
Termination of an episode, can be supplied with a reason for various purposes debugging or clarificat...
void Register(IEnvironmentListener environment_listener, string identifier)
System.Object Object
void Register(IConfigurable configurable, string identifier)
override EnvironmentState ReactAndCollectState(Reaction reaction)