CameraCreator.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * author: Jana-Sophie Schönfeld, Lydia Ebbinghaus
  3. */
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using UnityEngine;
  7. using System;
  8. using Valve.VR.InteractionSystem;
  9. using Valve.VR.InteractionSystem.Sample;
  10. using RosSharp.RosBridgeClient;
  11. // Attached to GameObject VRCamera (> SteamVRObjects > Player) in the hierachy.
  12. // Class that creates object on which image data of real cameras is rendered, sort out not used cameras and updates camera images in menu.
  13. // It is possible to attach cameras to a parent see line 121.
  14. public class CameraCreator : MonoBehaviour
  15. {
  16. private bool gotTopics = false;
  17. public bool topicsSorted = false;
  18. //private GameObject allCameras;
  19. public string[] topics;
  20. public bool finishedUpdating;
  21. public GameObject cameraParent;
  22. public GameObject cameraPlane;
  23. private MeshRenderer mesh;
  24. // Dictonarys of camernames and corresponding image data.
  25. Dictionary<string, byte[]> dict;
  26. Dictionary<string,byte[]> update;
  27. // Start is called before the first frame update.
  28. void Start()
  29. {
  30. if (cameraParent == null || cameraPlane == null) Debug.LogError("CameraCreator.cs: Prefab missing. Please head over to the inspector and make sure Prefabs are dragged into cameraParent and cameraPlane. Script attached to VRCamera > SteamVRObjects > Player");
  31. }
  32. // Update is called once per frame.
  33. // As soon as it got the camera topics from the RosBridge CreateCams() is called.
  34. // Calling CreateCams() is a one time action.
  35. void Update()
  36. {
  37. if (!gotTopics)
  38. {
  39. topics = GameObject.Find("RosBridge").GetComponent<CameraServiceSubscriber>().topics;
  40. dict = new Dictionary<string, byte[]>();
  41. if (topics.Length > 0)
  42. {
  43. SortOutTopics();
  44. gotTopics = !gotTopics;
  45. Destroy(GameObject.Find("RosBridge").GetComponent<CameraServiceSubscriber>());
  46. }
  47. }
  48. }
  49. // Called from VRInput if user opens menu again. Updates camera images in menu. Calls UpdateCameraImages to get image date of one camera.
  50. public void updateCams()
  51. {
  52. update = new Dictionary<string, byte[]>();
  53. finishedUpdating = false;
  54. var lastElement = false;
  55. var index = 0;
  56. foreach(string currentCamera in dict.Keys)
  57. {
  58. var currentImageSubscriber = GameObject.Find("RosBridge").AddComponent<ImageSubscriberMod>();
  59. currentImageSubscriber.stopProcessing = true;
  60. currentImageSubscriber.Topic = currentCamera;
  61. if(index == dict.Count-1) lastElement=true;
  62. index++;
  63. StartCoroutine(UpdateCameraImages(currentImageSubscriber,currentCamera,lastElement));
  64. }
  65. }
  66. // Waits 5 seconds, gets current camera image and stores name and corresponding imaga data in a dictonary.
  67. // last = true, if currentCamera is the last one to be updated.
  68. IEnumerator UpdateCameraImages(ImageSubscriberMod currentImageSubscriber, string currentCamera, bool last)
  69. {
  70. yield return new WaitForSeconds(5);
  71. if(!currentImageSubscriber.oneMessageReceived)
  72. {
  73. Debug.Log("CameraCreator.cs: Topic: "+ currentImageSubscriber.Topic + " not published");
  74. }
  75. else
  76. {
  77. byte[] imageData = currentImageSubscriber.imageData;
  78. update.Add(currentCamera,imageData);
  79. }
  80. Destroy(currentImageSubscriber);
  81. if(last)
  82. {
  83. dict = update;
  84. Debug.Log("CameraCreator.cs: Camera Images Updated");
  85. finishedUpdating=true;
  86. }
  87. }
  88. // Sorts out non publishing topics and writes publishing ones in the directionary.
  89. public void SortOutTopics()
  90. {
  91. Debug.Log("CameraCreator.cs: Sorting out not used Cameras.");
  92. var amountOfCameras = topics.Length;
  93. for (int i = 0; i < amountOfCameras; i++)
  94. {
  95. // Object image will be loading on.
  96. var currentCamera = Instantiate(cameraPlane,this.transform.position,this.transform.rotation);
  97. currentCamera.transform.SetParent(cameraParent.transform);
  98. // Making plane an interactable object, so it can be dragged.
  99. currentCamera.AddComponent<Interactable>();
  100. var interactableExp = currentCamera.AddComponent<InteractableExampleMod>();
  101. interactableExp.camera = this.transform;
  102. // Enable to attach cameras to a parent, like VRCamera.
  103. //currentCamera.transform.SetParent(cameraParent.transform);
  104. // Loading images onto object.
  105. var currentImageSubscriber = GameObject.Find("RosBridge").AddComponent<ImageSubscriberMod>();
  106. currentImageSubscriber.meshRenderer = currentCamera.GetComponent<MeshRenderer>();
  107. currentImageSubscriber.Topic = topics[i];
  108. currentCamera.SetActive(false);
  109. currentCamera.name=topics[i];
  110. // Checks if currentCamera is publishing any image Data.
  111. StartCoroutine(CheckCamera(i,currentImageSubscriber,currentCamera,amountOfCameras));
  112. }
  113. }
  114. // Checks if currentCamera is publishing any image data and destroys image subsciber afterwards (improves runtime).
  115. // i = index of currentCamera in diconary.
  116. IEnumerator CheckCamera(int i, ImageSubscriberMod currentImageSubscriber, GameObject currentCamera,int amountOfCameras)
  117. {
  118. yield return new WaitForSecondsRealtime(5);
  119. Debug.Log("CameraCreator.cs: Loading Camera image of: "+ topics[i]);
  120. if(!currentImageSubscriber.oneMessageReceived)
  121. {
  122. Debug.Log("CameraCreator.cs: Topic: "+ topics[i] + " not published");
  123. Destroy(currentCamera);
  124. }else
  125. {
  126. string topic = topics[i];
  127. byte[] imageData = currentImageSubscriber.imageData;
  128. try
  129. {
  130. dict.Add(topic, imageData);
  131. }
  132. catch (ArgumentException)
  133. {
  134. Debug.LogError("CameraCreator.cs: An element with Key = \"txt\" already exists. Duplicate of camera exists");
  135. }
  136. }
  137. // If currentCamera == last camera all cameras that are not publishing any data are sorted out.
  138. if(i == (amountOfCameras-1))
  139. {
  140. topicsSorted = !topicsSorted;
  141. }
  142. Destroy(currentImageSubscriber);
  143. }
  144. // Returns image data of camera with name : cameraName.
  145. public byte[] getImageData(string cameraName)
  146. {
  147. try
  148. {
  149. return dict[cameraName];
  150. }
  151. catch(KeyNotFoundException)
  152. {
  153. Debug.LogError("CameraCreator.cs: Trying to access camera image that does not exist.");
  154. }
  155. return null;
  156. }
  157. // Returns dictonary that contains camera names and corresponding image data.
  158. public Dictionary<string, byte[]> getDictionary()
  159. {
  160. return dict;
  161. }
  162. }