Neodroid  0.2.0
Machine Learning Environment Prototyping Tool
PrototypingEnvironment.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Linq;
14 using UnityEngine;
15 using Object = System.Object;
16 
17 namespace droid.Runtime.Environments {
22  [AddComponentMenu("Neodroid/Environments/PrototypingEnvironment")]
25  #region NeodroidCallbacks
26 
30  protected override void Clear() {
31  this.Displayers.Clear();
32  this.Configurables.Clear();
33  this.Actuators.Clear();
34  this.Observers.Clear();
35  this.Listeners.Clear();
36  }
37 
42  public override Reaction SampleReaction() {
43  #if NEODROID_DEBUG
44  if (this.Debugging) {
45  Debug.Log($"Sampling a reaction for environment {this.Identifier}");
46  }
47  #endif
48 
49  this._Sample_Motions.Clear();
50 
51  foreach (var actuator in this.Actuators) {
52  var actor_value = actuator.Value;
53 
54  var actuator_value = actuator.Value;
55  if (actuator_value != null) {
56  this._Sample_Motions.Add(new ActuatorMotion(actuator.Key, actuator.Key, actuator_value.Sample()));
57  }
58  }
59 
60  if (this._Terminated) {
61  #if NEODROID_DEBUG
62  if (this.Debugging) {
63  Debug.Log("SampleReaction resetting environment");
64  }
65  #endif
66 
67  var reset_reaction =
68  new ReactionParameters(false, false, true, episode_count : true) {IsExternal = false};
69  return new Reaction(reset_reaction, this.Identifier);
70  }
71 
72  var rp = new ReactionParameters(true, true, episode_count : true) {IsExternal = false};
73  return new Reaction(rp, this._Sample_Motions.ToArray(), null, null, null, "", this.Identifier);
74  }
75 
76 
77 
78  #endregion
79 
80  #region PublicMethods
81 
82  #region Getters
83 
86  public Dictionary<string, IActuator> Actuators { get; } = new Dictionary<string, IActuator>();
87 
88 
89 
93  public override string PrototypingTypeName { get { return "PrototypingEnvironment"; } }
94 
95  #endregion
96 
97 
98 
99  #region Registration
100 
105  public void Register(IActuator obj) { this.Register(obj, obj.Identifier); }
106 
107  public void Register(IActuator obj, String identifier) {
108  if (!this.Actuators.ContainsKey(identifier)) {
109  #if NEODROID_DEBUG
110  if (this.Debugging) {
111  Debug.Log($"Environment {this.name} has registered actuator {identifier}");
112  }
113  #endif
114 
115  this.Actuators.Add(identifier, obj);
116  } else {
117  Debug.LogWarning($"WARNING! Please check for duplicates, Environment {this.name} already has actuator {identifier} registered");
118  }
119  }
120 
121  public void UnRegister(IActuator obj) { this.UnRegister(obj, obj.Identifier); }
122 
123  public void UnRegister(IActuator t, String obj) {
124  if (this.Actuators.ContainsKey(obj)) {
125  #if NEODROID_DEBUG
126  if (this.Debugging) {
127  Debug.Log($"Environment {this.name} unregistered observer {obj}");
128  }
129  #endif
130  this.Actuators.Remove(obj);
131  }
132  }
133 
134  #endregion
135 
136  #endregion
137 
138  #region PrivateMethods
139 
144  public override EnvironmentState CollectState() {
145  lock (this._Reaction_Lock) {
146  if (this.Actuators != null) {
147  foreach (var m in this.Actuators.Values) {
148  this._Energy_Spent += m.GetEnergySpend();
149  }
150  }
151 
152  var signal = 0f;
153 
154  if (this._objective_function != null) {
155  signal = this._objective_function.Evaluate();
156  }
157 
158  EnvironmentDescription description = null;
159  if (this._ReplyWithDescriptionThisStep) {
160  #if NEODROID_DEBUG
161  if (this.Debugging) {
162  Debug.Log("Describing Environment");
163  }
164  #endif
165  var threshold = 0f;
166  if (this._objective_function != null) {
167  threshold = this._objective_function.SolvedThreshold;
168  }
169 
170  var episode_length = 0;
171  if (this._objective_function) {
172  episode_length = this._objective_function.EpisodeLength;
173  }
174 
175  var virtual_actors = new Dictionary<String, IActor>();
176  virtual_actors.Add("All", new VirtualActor(this.Actuators));
177 
178  description =
179  new EnvironmentDescription(episode_length, virtual_actors, this.Configurables, threshold);
180  }
181 
182  this._Observables.Clear();
183  foreach (var item in this.Observers) {
184  if (item.Value != null) {
185  if (item.Value.FloatEnumerable != null) {
186  this._Observables.AddRange(item.Value.FloatEnumerable);
187  } else {
188  #if NEODROID_DEBUG
189  if (this.Debugging) {
190  Debug.Log($"Sensor with key {item.Key} has a null FloatEnumerable value");
191  }
192  #endif
193  }
194  } else {
195  #if NEODROID_DEBUG
196  if (this.Debugging) {
197  Debug.Log($"Sensor with key {item.Key} has a null value");
198  }
199  #endif
200  }
201  }
202 
203  var obs = this._Observables.ToArray();
204 
205  var time = Time.time - this._Lastest_Reset_Time;
206 
207  var state = new EnvironmentState(this.Identifier,
208  this._Energy_Spent,
209  this.CurrentFrameNumber,
210  time,
211  signal,
212  this._Terminated,
213  ref obs,
214  this.LastTerminationReason,
215  description);
216 
217  if (this._Simulation_Manager.SimulatorConfiguration.AlwaysSerialiseUnobservables
218  || this._ReplyWithDescriptionThisStep) {
219  state.Unobservables = new Unobservables(ref this._Tracked_Rigid_Bodies, ref this._Poses);
220  }
221 
222  if (this._Simulation_Manager.SimulatorConfiguration.AlwaysSerialiseIndividualObservables
223  || this._ReplyWithDescriptionThisStep) {
224  state.Observers = this.Observers.Values.ToArray();
225  }
226 
227  return state;
228  }
229  }
230 
235  public override void ObservationsString(DataPoller recipient) {
236  recipient.PollData(string.Join("\n\n",
237  this.Observers.Values.Select(e => $"{e.Identifier}:\n{e.ToString()}")));
238  }
239 
243  void SendToActuators(Reaction reaction) {
244  if (reaction.Motions != null && reaction.Motions.Length > 0) {
245  foreach (var motion in reaction.Motions) {
246  #if NEODROID_DEBUG
247  if (this.Debugging) {
248  Debug.Log("Applying " + motion + " To " + this.name + " actuator");
249  }
250  #endif
251  var motion_actuator_name = motion.ActuatorName;
252  if (this.Actuators.ContainsKey(motion_actuator_name)
253  && this.Actuators[motion_actuator_name] != null) {
254  this.Actuators[motion_actuator_name].ApplyMotion(motion);
255  } else {
256  #if NEODROID_DEBUG
257  if (this.Debugging) {
258  Debug.Log("Could find not actuator with the specified name: " + motion_actuator_name);
259  }
260  #endif
261  }
262  }
263  }
264  }
265 
269  protected override void InnerStep(Reaction reaction) { this.SendToActuators(reaction); }
270 
273  protected override void InnerResetRegisteredObjects() {
274  foreach (var actuator in this.Actuators.Values) {
275  actuator?.EnvironmentReset();
276  }
277  }
278 
279  #endregion
280  }
281 }
Has a possible direction given by the sign of the float in strength
Definition: MotorMotion.cs:9
Environment to be used with the prototyping components.
override void ObservationsString(DataPoller recipient)
void Register(IActuator obj, String identifier)