Neodroid  0.2.0
Machine Learning Environment Prototyping Tool
NeodroidUtilities.cs
Go to the documentation of this file.
1 using System.Collections.Generic;
6 using UnityEngine;
7 using UnityEngine.SceneManagement;
8 
9 namespace droid.Runtime.Utilities.Misc {
12  public static class NeodroidUtilities {
16  public static Vector4 Zero { get { return new Vector4(0, 0, 0, 0); } }
17 
22  public static float KineticEnergy(Rigidbody rb) {
23  return
24  0.5f
25  * rb.mass
26  * Mathf.Pow(rb.velocity.magnitude,
27  2); // mass in kg, velocity in meters per second, result is joules
28  }
29 
36  public static Vector3 Vector3Clamp(ref Vector3 vec, Vector3 min_point, Vector3 max_point) {
37  vec.x = Mathf.Clamp(vec.x, min_point.x, max_point.x);
38  vec.y = Mathf.Clamp(vec.y, min_point.y, max_point.y);
39  vec.z = Mathf.Clamp(vec.z, min_point.z, max_point.z);
40  return vec;
41  }
42 
48  public static void DrawLine(Vector3 p1, Vector3 p2, float width) {
49  var count = Mathf.CeilToInt(width); // how many lines are needed.
50  if (count == 1) {
51  Gizmos.DrawLine(p1, p2);
52  } else {
53  var c = Camera.current;
54  if (c == null) {
55  Debug.LogError("Camera.current is null");
56  return;
57  }
58 
59  var v1 = (p2 - p1).normalized; // line direction
60  var v2 = (c.transform.position - p1).normalized; // direction to camera
61  var n = Vector3.Cross(v1, v2); // normal vector
62  for (var i = 0; i < count; i++) {
63  //Vector3 o = n * width ((float)i / (count - 1) - 0.5f);
64  var o = n * width * ((float)i / (count - 1) - 0.5f);
65  Gizmos.DrawLine(p1 + o, p2 + o);
66  }
67  }
68  }
69 
74  public static AnimationCurve DefaultAnimationCurve() {
75  return new AnimationCurve(new Keyframe(1, 1), new Keyframe(0, 0));
76  }
77 
81  public static Gradient DefaultGradient() {
82  var gradient = new Gradient {
83  // The number of keys must be specified in this array initialiser
84  colorKeys = new[] {
85  // Add your colour and specify the stop point
86  new GradientColorKey(new Color(1, 1, 1), 0),
87  new GradientColorKey(new Color(1, 1, 1), 1f),
88  new GradientColorKey(new Color(1, 1, 1), 0)
89  },
90  // This sets the alpha to 1 at both ends of the gradient
91  alphaKeys = new[] {
92  new GradientAlphaKey(1, 0),
93  new GradientAlphaKey(1, 1),
94  new GradientAlphaKey(1, 0)
95  }
96  };
97 
98  return gradient;
99  }
100 
106  public static Texture2D RenderTextureImage(Camera camera) {
107  // From unity documentation, https://docs.unity3d.com/ScriptReference/Camera.Render.html
108  var current_render_texture = RenderTexture.active;
109  RenderTexture.active = camera.targetTexture;
110  camera.Render();
111  var target_texture = camera.targetTexture;
112  var texture = new Texture2D(target_texture.width, target_texture.height);
113  texture.ReadPixels(new Rect(0, 0, target_texture.width, target_texture.height), 0, 0);
114  texture.Apply();
115  RenderTexture.active = current_render_texture;
116  return texture;
117  }
118 
134  public static void
135  RegisterCollisionTriggerCallbacksOnChildren<TChildColliderSensor, TCollider, TCollision>(
136  Component caller,
137  Transform parent,
139  = null,
141  null,
143  null,
145  null,
147  null,
149  null,
150  bool debug = false)
151  where TChildColliderSensor : ChildColliderSensor<TCollider, TCollision> where TCollider : Component {
152  var children_with_colliders = parent.GetComponentsInChildren<TCollider>();
153 
154  //TODO add check and warning for not all callbacks = null
155 
156  foreach (var child in children_with_colliders) {
157  var child_sensors = child.GetComponents<TChildColliderSensor>();
158  ChildColliderSensor<TCollider, TCollision> collider_sensor = null;
159  foreach (var child_sensor in child_sensors) {
160  if (child_sensor.Caller != null && child_sensor.Caller == caller) {
161  collider_sensor = child_sensor;
162  break;
163  }
164 
165  if (child_sensor.Caller == null) {
166  child_sensor.Caller = caller;
167  collider_sensor = child_sensor;
168  break;
169  }
170  }
171 
172  if (collider_sensor == null) {
173  collider_sensor = child.gameObject.AddComponent<TChildColliderSensor>();
174  collider_sensor.Caller = caller;
175  }
176 
177  if (on_collision_enter_child != null) {
178  collider_sensor.OnCollisionEnterDelegate = on_collision_enter_child;
179  }
180 
181  if (on_trigger_enter_child != null) {
182  collider_sensor.OnTriggerEnterDelegate = on_trigger_enter_child;
183  }
184 
185  if (on_collision_exit_child != null) {
186  collider_sensor.OnCollisionExitDelegate = on_collision_exit_child;
187  }
188 
189  if (on_trigger_exit_child != null) {
190  collider_sensor.OnTriggerExitDelegate = on_trigger_exit_child;
191  }
192 
193  if (on_trigger_stay_child != null) {
194  collider_sensor.OnTriggerStayDelegate = on_trigger_stay_child;
195  }
196 
197  if (on_collision_stay_child != null) {
198  collider_sensor.OnCollisionStayDelegate = on_collision_stay_child;
199  }
200 
201  #if NEODROID_DEBUG
202  if (debug) {
203  Debug.Log($"{caller.name} has created {collider_sensor.name} on {child.name} under parent {parent.name}");
204  }
205  #endif
206  }
207  }
208 
213  public static string ColorArrayToString(IEnumerable<Color> colors) {
214  var s = "";
215  foreach (var color in colors) {
216  s += color.ToString();
217  }
218 
219  return s;
220  }
221 
222  public static IHasRegister<IActuator> RegisterComponent< TCaller>(
224  TCaller c,
225  bool only_parents = false,
226  bool debug = false)
227  where TCaller : Component, IRegisterable {
228 
229 
230  IHasRegister<IActuator> component = null;
231  if (r != null) {
232  component = r; //.GetComponent<Recipient>();
233  }
234  else{
235 
236  if (c.GetComponentInParent<Actor>() != null) {
237  component = c.GetComponentInParent<Actor>();
238  } else if (!only_parents) {
239  component = Object.FindObjectOfType<Actor>();
240  }
241  }
242 
243  if (component == null){
244  if (c.GetComponentInParent<PrototypingEnvironment>() != null) {
245  component = c.GetComponentInParent<PrototypingEnvironment>();
246  } else if (!only_parents) {
247  component = Object.FindObjectOfType<PrototypingEnvironment>();
248  }
249 
250  }
251 
252  if (component != null) {
253  component.Register((IActuator)c);
254  } else {
255  #if NEODROID_DEBUG
256  if (debug) {
257  Debug.Log($"Could not find a IHasRegister<IActuator> recipient during registration");
258  }
259  #endif
260  }
261 
262  return component;
263  }
264 
275  public static IHasRegister<IActuator> RegisterComponent< TCaller>(
277  TCaller c,
278  string identifier,
279  bool only_parents = false,
280  bool debug = false)
281  where TCaller : Component, IRegisterable {
282 
283 
284  IHasRegister<IActuator> component = null;
285  if (r != null) {
286  component = r; //.GetComponent<Recipient>();
287  }
288  else{
289 
290  if (c.GetComponentInParent<Actor>() != null) {
291  component = c.GetComponentInParent<Actor>();
292  } else if (!only_parents) {
293  component = Object.FindObjectOfType<Actor>();
294  }
295  }
296 
297  if (component == null){
298  if (c.GetComponentInParent<PrototypingEnvironment>() != null) {
299  component = c.GetComponentInParent<PrototypingEnvironment>();
300  } else if (!only_parents) {
301  component = Object.FindObjectOfType<PrototypingEnvironment>();
302  }
303 
304  }
305 
306  if (component != null) {
307  component.Register((IActuator)c, identifier);
308  } else {
309  #if NEODROID_DEBUG
310  if (debug) {
311  Debug.Log($"Could not find a IHasRegister<IActuator> recipient during registration");
312  }
313  #endif
314  }
315 
316 
317  return component;
318  }
319 
320 
330  public static TRecipient RegisterComponent<TRecipient, TCaller>(
331  TRecipient r,
332  TCaller c,
333  bool only_parents = false,
334  bool debug = false)
335  where TRecipient : Object, IHasRegister<TCaller> where TCaller : Component, IRegisterable {
336 
337 
338  TRecipient component = null;
339  if (r != null) {
340  component = r; //.GetComponent<Recipient>();
341  } else if (c.GetComponentInParent<TRecipient>() != null) {
342  component = c.GetComponentInParent<TRecipient>();
343  } else if (!only_parents) {
344  component = Object.FindObjectOfType<TRecipient>();
345  }
346 
347  if (component != null) {
348  component.Register(c);
349  } else {
350  #if NEODROID_DEBUG
351  if (debug) {
352  Debug.Log($"Could not find a {typeof(TRecipient)} recipient during registration");
353  }
354  #endif
355  }
356 
357  return component;
358  }
359 
370  public static TRecipient RegisterComponent<TRecipient, TCaller>(
371  TRecipient r,
372  TCaller c,
373  string identifier,
374  bool only_parents = false,
375  bool debug = false)
376  where TRecipient : Object, IHasRegister<TCaller> where TCaller : Component, IRegisterable {
377  TRecipient component = null;
378  if (r != null) {
379  component = r;
380  } else if (c.GetComponentInParent<TRecipient>() != null) {
381  component = c.GetComponentInParent<TRecipient>();
382  } else if (!only_parents) {
383  component = Object.FindObjectOfType<TRecipient>();
384  }
385 
386  if (component != null) {
387  component.Register(c, identifier);
388  } else {
389  #if NEODROID_DEBUG
390  if (debug) {
391  Debug.Log($"Could not find a {typeof(TRecipient)} recipient during registeration");
392  }
393 
394  #endif
395  }
396 
397  return component;
398  }
399 
402  public static T[] FindAllObjectsOfTypeInScene<T>() {
403  //(Scene scene) {
404  var results = new List<T>();
405  for (var i = 0; i < SceneManager.sceneCount; i++) {
406  var s = SceneManager.GetSceneAt(i); // maybe EditorSceneManager
407  if (!s.isLoaded) {
408  continue;
409  }
410 
411  var all_game_objects = s.GetRootGameObjects();
412  foreach (var go in all_game_objects) {
413  results.AddRange(go.GetComponentsInChildren<T>(true));
414  }
415  }
416 
417  return results.ToArray();
418  }
419 
424  public static GameObject[] FindAllGameObjectsExceptLayer(int layer) {
425  var goa = Object.FindObjectsOfType<GameObject>();
426  var game_objects = new List<GameObject>();
427  foreach (var go in goa) {
428  if (go.layer != layer) {
429  game_objects.Add(go);
430  }
431  }
432 
433  return game_objects.ToArray();
434  }
435 
441  public static Vector3 BroadcastVector3(this float a) { return new Vector3 {x = a, y = a, z = a}; }
442 
448  public static Vector2 BroadcastVector2(this float a) { return new Vector2 {x = a, y = a}; }
449 
455  public static Vector4 BroadcastVector4(this float a) { return new Vector4 {x = a, y = a, z = a}; }
456 
462  public static GameObject[] RecursiveChildGameObjectsExceptLayer(Transform parent, int layer) {
463  var game_objects = new List<GameObject>();
464  foreach (Transform go in parent) {
465  if (go) {
466  if (go.gameObject.layer != layer) {
467  game_objects.Add(go.gameObject);
468  var children = RecursiveChildGameObjectsExceptLayer(go, layer);
469  if (children != null && children.Length > 0) {
470  game_objects.AddRange(children);
471  }
472  }
473  }
474  }
475 
476  return game_objects.ToArray();
477  }
478 
480  /*public Texture2D ObservationToTex(Camera camera, int width, int height)
481  {
482  Camera cam = camera;
483  Rect oldRec = camera.rect;
484  cam.rect = new Rect(0f, 0f, 1f, 1f);
485  bool supportsAntialiasing = false;
486  bool needsRescale = false;
487  var depth = 24;
488  var format = RenderTextureFormat.Default;
489  var readWrite = RenderTextureReadWrite.Default;
490  var antiAliasing = (supportsAntialiasing) ? Mathf.Max(1, QualitySettings.antiAliasing) : 1;
491 
492  var finalRT =
493  RenderTexture.GetTemporary(width, height, depth, format, readWrite, antiAliasing);
494  var renderRT = (!needsRescale) ? finalRT :
495  RenderTexture.GetTemporary(width, height, depth, format, readWrite, antiAliasing);
496  var tex = new Texture2D(width, height, TextureFormat.RGB24, false);
497 
498  var prevActiveRT = RenderTexture.active;
499  var prevCameraRT = cam.targetTexture;
500 
501  // render to offscreen texture ( from CPU side)
502  RenderTexture.active = renderRT;
503  cam.targetTexture = renderRT;
504 
505  cam.Render();
506 
507  if (needsRescale)
508  {
509  RenderTexture.active = finalRT;
510  Graphics.Blit(renderRT, finalRT);
511  RenderTexture.ReleaseTemporary(renderRT);
512  }
513 
514  tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0);
515  tex.Apply();
516  cam.targetTexture = prevCameraRT;
517  cam.rect = oldRec;
518  RenderTexture.active = prevActiveRT;
519  RenderTexture.ReleaseTemporary(finalRT);
520  return tex;
521  }
522 
525  public List<float[,,,]> GetObservationMatrixList(List<int> agent_keys)
526  {
527  List<float[,,,]> observation_matrix_list = new List<float[,,,]>();
528  Dictionary<int, List<Camera>> observations = CollectObservations();
529  for (int obs_number = 0; obs_number < brainParameters.cameraResolutions.Length; obs_number++)
530  {
531  int width = brainParameters.cameraResolutions[obs_number].width;
532  int height = brainParameters.cameraResolutions[obs_number].height;
533  bool bw = brainParameters.cameraResolutions[obs_number].blackAndWhite;
534  int pixels = 0;
535  if (bw)
536  pixels = 1;
537  else
538  pixels = 3;
539  float[,,,] observation_matrix = new float[agent_keys.Count
540  , height
541  , width
542  , pixels];
543  int i = 0;
544  foreach (int k in agent_keys)
545  {
546  Camera agent_obs = observations[k][obs_number];
547  Texture2D tex = ObservationToTex(agent_obs, width, height);
548  for (int w = 0; w < width; w++)
549  {
550  for (int h = 0; h < height; h++)
551  {
552  Color c = tex.GetPixel(w, h);
553  if (!bw)
554  {
555  observation_matrix[i, tex.height - h - 1, w, 0] = c.r;
556  observation_matrix[i, tex.height - h - 1, w, 1] = c.g;
557  observation_matrix[i, tex.height - h - 1, w, 2] = c.b;
558  }
559  else
560  {
561  observation_matrix[i, tex.height - h - 1, w, 0] = (c.r + c.g + c.b) / 3;
562  }
563  }
564  }
565  UnityEngine.Object.DestroyImmediate(tex);
566  Resources.UnloadUnusedAssets();
567  i++;
568  }
569  observation_matrix_list.Add(observation_matrix);
570  }
571  return observation_matrix_list;
572  }*/
573  }
574 }
delegate void OnChildCollisionEnterDelegate(GameObject child_sensor_game_object, TCollision collision)
delegate void OnChildTriggerExitDelegate(GameObject child_sensor_game_object, TCollider collider)
delegate void OnChildTriggerEnterDelegate(GameObject child_sensor_game_object, TCollider collider)
delegate void OnChildCollisionStayDelegate(GameObject child_sensor_game_object, TCollision collision)
Environment to be used with the prototyping components.
delegate void OnChildTriggerStayDelegate(GameObject child_sensor_game_object, TCollider collider)
delegate void OnChildCollisionExitDelegate(GameObject child_sensor_game_object, TCollision collision)