Neodroid  0.2.0
Machine Learning Environment Prototyping Tool
ActorisedPrototypingEnvironment.cs
Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Linq;
6 using UnityEngine;
7 
8 namespace droid.Runtime.Environments {
13  [AddComponentMenu("Neodroid/Environments/ActorisedPrototypingEnvironment")]
16  #region NeodroidCallbacks
17 
21  protected override void Clear() {
22  this.Displayers.Clear();
23  this.Configurables.Clear();
24  this.Actors.Clear();
25  this.Observers.Clear();
26  this.Listeners.Clear();
27  }
28 
33  public override Reaction SampleReaction() {
34  #if NEODROID_DEBUG
35  if (this.Debugging) {
36  Debug.Log($"Sampling a reaction for environment {this.Identifier}");
37  }
38  #endif
39 
40  this._Sample_Motions.Clear();
41 
42  foreach (var actor in this.Actors) {
43  var actor_value = actor.Value;
44  if (actor_value?.Actuators != null) {
45  foreach (var actuator in actor_value.Actuators) {
46  var actuator_value = actuator.Value;
47  if (actuator_value != null) {
48  this._Sample_Motions.Add(new ActuatorMotion(actor.Key, actuator.Key, actuator_value.Sample()));
49  }
50  }
51  }
52  }
53 
54  if (this._Terminated) {
55  #if NEODROID_DEBUG
56  if (this.Debugging) {
57  Debug.Log("SampleReaction resetting environment");
58  }
59  #endif
60 
61  var reset_reaction =
62  new ReactionParameters(false, false, true, episode_count : true) {IsExternal = false};
63  return new Reaction(reset_reaction, this.Identifier);
64  }
65 
66  var rp = new ReactionParameters(true, true, episode_count : true) {IsExternal = false};
67  return new Reaction(rp, this._Sample_Motions.ToArray(), null, null, null, "", this.Identifier);
68  }
69 
70 
71 
72  #endregion
73 
74  #region PublicMethods
75 
76  #region Getters
77 
80  public Dictionary<string, IActor> Actors { get; } = new Dictionary<string, IActor>();
81 
82  #endregion
83 
84 
90  public override EnvironmentState ReactAndCollectState(Reaction reaction) {
91  this.React(reaction);
92 
93  return this.CollectState();
94  }
95 
96  #region Registration
97 
102  public void Register(IActor actor) { this.Register(actor, actor.Identifier); }
103 
109  public void Register(IActor actor, string identifier) {
110  if (!this.Actors.ContainsKey(identifier)) {
111  #if NEODROID_DEBUG
112  if (this.Debugging) {
113  Debug.Log($"Environment {this.name} has registered actor {identifier}");
114  }
115  #endif
116 
117  this.Actors.Add(identifier, actor);
118  } else {
119  Debug.LogWarning($"WARNING! Please check for duplicates, Environment {this.name} already has actor {identifier} registered");
120  }
121  }
122 
126  public void UnRegister(IActor actor) { this.UnRegister(actor, actor.Identifier); }
127 
128  public void UnRegister(IActor t, string obj) {
129  if (this.Actors.ContainsKey(obj)) {
130  #if NEODROID_DEBUG
131  if (this.Debugging) {
132  Debug.Log($"Environment {this.name} unregistered actor {obj}");
133  }
134  #endif
135  this.Actors.Remove(obj);
136  }
137  }
138 
139  #endregion
140 
141  #endregion
142 
143  #region PrivateMethods
144 
149  public override EnvironmentState CollectState() {
150  lock (this._Reaction_Lock) {
151  if (this.Actors != null) {
152  foreach (var a in this.Actors.Values) {
153  if (a.Actuators != null) {
154  foreach (var m in a.Actuators.Values) {
155  this._Energy_Spent += m.GetEnergySpend();
156  }
157  }
158  }
159  }
160 
161  var signal = 0f;
162 
163  if (this._objective_function != null) {
164  signal = this._objective_function.Evaluate();
165  }
166 
167  EnvironmentDescription description = null;
168  if (this._ReplyWithDescriptionThisStep) {
169  #if NEODROID_DEBUG
170  if (this.Debugging) {
171  Debug.Log("Describing Environment");
172  }
173  #endif
174  var threshold = 0f;
175  if (this._objective_function != null) {
176  threshold = this._objective_function.SolvedThreshold;
177  }
178 
179  var episode_length = 0;
180  if (this._objective_function) {
181  episode_length = this._objective_function.EpisodeLength;
182  }
183 
184  description =
185  new EnvironmentDescription(episode_length, this.Actors, this.Configurables, threshold);
186  }
187 
188  this._Observables.Clear();
189  foreach (var item in this.Observers) {
190  if (item.Value != null) {
191  if (item.Value.FloatEnumerable != null) {
192  this._Observables.AddRange(item.Value.FloatEnumerable);
193  } else {
194  #if NEODROID_DEBUG
195  if (this.Debugging) {
196  Debug.Log($"Sensor with key {item.Key} has a null FloatEnumerable value");
197  }
198  #endif
199  }
200  } else {
201  #if NEODROID_DEBUG
202  if (this.Debugging) {
203  Debug.Log($"Sensor with key {item.Key} has a null value");
204  }
205  #endif
206  }
207  }
208 
209  var obs = this._Observables.ToArray();
210 
211  var time = Time.time - this._Lastest_Reset_Time;
212 
213  var state = new EnvironmentState(this.Identifier,
214  this._Energy_Spent,
215  this.CurrentFrameNumber,
216  time,
217  signal,
218  this._Terminated,
219  ref obs,
220  this.LastTerminationReason,
221  description);
222 
223  if (this._Simulation_Manager.SimulatorConfiguration.AlwaysSerialiseUnobservables
224  || this._ReplyWithDescriptionThisStep) {
225  state.Unobservables = new Unobservables(ref this._Tracked_Rigid_Bodies, ref this._Poses);
226  }
227 
228  if (this._Simulation_Manager.SimulatorConfiguration.AlwaysSerialiseIndividualObservables
229  || this._ReplyWithDescriptionThisStep) {
230  state.Observers = this.Observers.Values.ToArray();
231  }
232 
233  return state;
234  }
235  }
236 
241  public override void ObservationsString(DataPoller recipient) {
242  recipient.PollData(string.Join("\n\n",
243  this.Observers.Values.Select(e => $"{e.Identifier}:\n{e.ToString()}")));
244  }
245 
249  void SendToDisplayers(Reaction reaction) {
250  if (reaction.Displayables != null && reaction.Displayables.Length > 0) {
251  foreach (var displayable in reaction.Displayables) {
252  #if NEODROID_DEBUG
253  if (this.Debugging) {
254  Debug.Log("Applying " + displayable + " To " + this.name + "'s displayers");
255  }
256  #endif
257  var displayable_name = displayable.DisplayableName;
258  if (this.Displayers.ContainsKey(displayable_name) && this.Displayers[displayable_name] != null) {
259  var v = displayable.DisplayableValue;
260  this.Displayers[displayable_name].Display(v);
261  } else {
262  #if NEODROID_DEBUG
263  if (this.Debugging) {
264  Debug.Log("Could find not displayer with the specified name: " + displayable_name);
265  }
266  #endif
267  }
268  }
269  }
270  }
271 
275  void SendToActuators(Reaction reaction) {
276  if (reaction.Motions != null && reaction.Motions.Length > 0) {
277  foreach (var motion in reaction.Motions) {
278  #if NEODROID_DEBUG
279  if (this.Debugging) {
280  Debug.Log("Applying " + motion + " To " + this.name + "'s actors");
281  }
282  #endif
283  var motion_actor_name = motion.ActorName;
284  if (this.Actors.ContainsKey(motion_actor_name) && this.Actors[motion_actor_name] != null) {
285  this.Actors[motion_actor_name].ApplyMotion(motion);
286  } else {
287  #if NEODROID_DEBUG
288  if (this.Debugging) {
289  Debug.Log("Could find not actor with the specified name: " + motion_actor_name);
290  }
291  #endif
292  }
293  }
294  }
295  }
296 
300  protected override void InnerStep(Reaction reaction) { this.SendToActuators(reaction); }
301 
304  protected override void InnerResetRegisteredObjects() {
305  foreach (var actor in this.Actors.Values) {
306  actor?.EnvironmentReset();
307  }
308  }
309 
310  #region EnvironmentStateSetters
311 
312  #endregion
313 
314  #endregion
315  }
316 }
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.