RKSensorAPI.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using Newtonsoft.Json;
  5. using System.Runtime.InteropServices;
  6. using Rokid.UXR.Native;
  7. using Rokid.UXR.Utility;
  8. //using Google.XR.Cardboard;
  9. namespace Rokid.UXR.Module
  10. {
  11. public class RKSensorAPI : MonoSingleton<RKSensorAPI>
  12. {
  13. public class OSTInfo
  14. {
  15. public CameraIntrinsices camera;
  16. }
  17. public class CameraIntrinsices
  18. {
  19. public string model;
  20. public string shutter;
  21. public double fx;
  22. public double fy;
  23. public double cx;
  24. public double cy;
  25. public double k1;
  26. public double k2;
  27. public double k3;
  28. public double p1;
  29. public double p2;
  30. public float fl;
  31. public K k;
  32. public int width;
  33. public int height;
  34. public double cameraReadoutTime;
  35. public double cameraDelayTime;
  36. }
  37. public class K
  38. {
  39. public int rows;
  40. public int cols;
  41. public double[] data;
  42. }
  43. public struct YUVImage
  44. {
  45. /// <summary>
  46. /// YUV 图像数据
  47. /// </summary>
  48. public byte[] yuvBytes;
  49. /// <summary>
  50. /// 时间戳
  51. /// </summary>
  52. public long timeStamp;
  53. /// <summary>
  54. /// 是否成功获取数据
  55. /// </summary>
  56. public bool success;
  57. }
  58. public class IMUData
  59. {
  60. public long mGlassSensorTimeStamp;
  61. public float[] mGlassAccData;
  62. public float[] mGlassMagnetData;
  63. public float[] mGlassGyroData;
  64. public long mGlassRotationTimeStamp;
  65. public float[] mGlassGameRotationData;
  66. public float[] mGlassRotationData;
  67. }
  68. /// <summary>
  69. /// 图片数据cache
  70. /// </summary>
  71. private YUVImage imageData;
  72. private int width, height;
  73. private bool isInitCameraPreview, isInitImu;
  74. private bool getCameraData, getImuData;
  75. private bool onUsbDeviceInited;
  76. private double lastTimeStamp = 0;
  77. private IMUData imuData;
  78. private void InitCameraPreview()
  79. {
  80. NativeInterface.NativeAPI.StartCameraPreview();
  81. NativeInterface.NativeAPI.SetCameraPreviewDataType(2);
  82. width = NativeInterface.NativeAPI.GetPreviewWidth();
  83. height = NativeInterface.NativeAPI.GetPreivewHeight();
  84. NativeInterface.NativeAPI.OnCameraDataUpdate += OnCameraDataUpdate;
  85. imageData = new YUVImage()
  86. {
  87. yuvBytes = new byte[Convert.ToInt32(width * height * 1.5f)],
  88. timeStamp = 0
  89. };
  90. isInitCameraPreview = true;
  91. }
  92. private void ReleaseCameraPreview()
  93. {
  94. if (isInitCameraPreview)
  95. {
  96. NativeInterface.NativeAPI.StopCameraPreview();
  97. NativeInterface.NativeAPI.ClearCameraDataUpdate();
  98. isInitCameraPreview = false;
  99. }
  100. }
  101. private void InitIMU()
  102. {
  103. RKLog.Info("====RKSensorAPI==== InitIMU");
  104. NativeInterface.NativeAPI.RegisterGlassSensorEvent();
  105. NativeInterface.NativeAPI.RegisterRotationEvent();
  106. NativeInterface.NativeAPI.OnGlassIMURotationUpdate += OnGlassIMURotationUpdate;
  107. NativeInterface.NativeAPI.OnGlassIMUSensorUpdate += OnGlassIMUSensorUpdate;
  108. imuData = new IMUData()
  109. {
  110. mGlassSensorTimeStamp = 0,
  111. mGlassAccData = new float[3],
  112. mGlassMagnetData = new float[3],
  113. mGlassGyroData = new float[3],
  114. mGlassGameRotationData = new float[4],
  115. mGlassRotationData = new float[4]
  116. };
  117. isInitImu = true;
  118. }
  119. private void ReleaseIMU()
  120. {
  121. if (isInitImu)
  122. {
  123. NativeInterface.NativeAPI.UnregisterRotationEvent();
  124. NativeInterface.NativeAPI.UnregisterGlassSensorEvent();
  125. NativeInterface.NativeAPI.OnGlassIMURotationUpdate -= OnGlassIMURotationUpdate;
  126. NativeInterface.NativeAPI.OnGlassIMUSensorUpdate -= OnGlassIMUSensorUpdate;
  127. isInitImu = false;
  128. }
  129. }
  130. private void OnGlassIMUSensorUpdate(float[] acc, float[] gyr, float[] gnt, long timeStamp)
  131. {
  132. this.imuData.mGlassAccData = acc;
  133. this.imuData.mGlassGyroData = gyr;
  134. this.imuData.mGlassMagnetData = gnt;
  135. this.imuData.mGlassSensorTimeStamp = timeStamp;
  136. //计算IMU帧率,时间为纳秒
  137. CalIMUFPS(timeStamp);
  138. }
  139. private void CalIMUFPS(long timeStamp)
  140. {
  141. float delta;
  142. double currentTimeStamp = timeStamp;
  143. if (lastTimeStamp == 0)
  144. {
  145. delta = 1;
  146. }
  147. else
  148. {
  149. delta = (float)((currentTimeStamp - lastTimeStamp) / 1000000000);
  150. RKLog.Debug("====RKSensorAPI====: CalIMUFPS " + delta);
  151. }
  152. lastTimeStamp = currentTimeStamp;
  153. Loom.QueueOnMainThread(() =>
  154. {
  155. OnIMUUpdate?.Invoke(delta);
  156. });
  157. OnIMUDataCallBack?.Invoke(imuData);
  158. }
  159. private void OnGlassIMURotationUpdate(float[] gameRot, float[] rot, long timeStamp)
  160. {
  161. this.imuData.mGlassGameRotationData = gameRot;
  162. this.imuData.mGlassRotationData = rot;
  163. this.imuData.mGlassRotationTimeStamp = timeStamp;
  164. }
  165. private void OnCameraDataUpdate(int width, int height, byte[] data, long timestamp)
  166. {
  167. if (this.imageData.timeStamp != timestamp)
  168. {
  169. this.imageData.success = true;
  170. this.imageData.yuvBytes = data;
  171. this.imageData.timeStamp = timestamp;
  172. }
  173. }
  174. protected override void OnDestroy()
  175. {
  176. base.OnDestroy();
  177. if (getCameraData)
  178. ReleaseCameraPreview();
  179. if (getImuData)
  180. ReleaseIMU();
  181. }
  182. private bool IsPreviewing()
  183. {
  184. return NativeInterface.NativeAPI.IsPreviewing();
  185. }
  186. private void OnApplicationPause(bool pauseStatus)
  187. {
  188. if (pauseStatus)
  189. {
  190. ReleaseCameraPreview();
  191. }
  192. }
  193. private void Update()
  194. {
  195. if (getCameraData && IsPreviewing())
  196. {
  197. if (isInitCameraPreview == false)
  198. {
  199. InitCameraPreview();
  200. }
  201. }
  202. if (onUsbDeviceInited == false && NativeInterface.NativeAPI.IsUSBConnect())
  203. {
  204. if (getImuData)
  205. {
  206. if (isInitImu == false)
  207. InitIMU();
  208. }
  209. onUsbDeviceInited = true;
  210. OnUsbDeviceInited?.Invoke();
  211. }
  212. }
  213. private double GetTimeStamp()
  214. {
  215. TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
  216. return ts.TotalMilliseconds;
  217. }
  218. #region API
  219. /// <summary>
  220. /// IMU数据回调,返回IMUData
  221. /// </summary>
  222. public static Action<IMUData> OnIMUDataCallBack;
  223. /// <summary>
  224. /// IMU刷新回调
  225. /// </summary>
  226. public static Action<float> OnIMUUpdate;
  227. /// <summary>
  228. /// USB初始化完成的回调
  229. /// </summary>
  230. public static Action OnUsbDeviceInited;
  231. /// <summary>
  232. /// 模块初始化
  233. /// </summary>
  234. public void Initialize(bool getCameraData, bool getImuData)
  235. {
  236. this.getCameraData = getCameraData;
  237. this.getImuData = getImuData;
  238. }
  239. /// <summary>
  240. /// 获取YUV数据
  241. /// </summary>
  242. /// <returns></returns>
  243. public YUVImage GetYUVImage()
  244. {
  245. return imageData;
  246. }
  247. /// <summary>
  248. /// 获取相机内参
  249. /// </summary>
  250. /// <returns></returns>
  251. [Obsolete("Use NativeInterface.NativeAPI.GetOSTInfo Instead")]
  252. public CameraIntrinsices GetCameraIntrinsices()
  253. {
  254. if (onUsbDeviceInited)
  255. {
  256. string data = NativeInterface.NativeAPI.GetOSTInfo();
  257. if (string.IsNullOrEmpty(data))
  258. {
  259. return null;
  260. }
  261. RKLog.Info($"====RokidSensorAPI==== CameraIntrinsices : {data}");
  262. Dictionary<string, object> dict = JsonConvert.DeserializeObject<Dictionary<string,
  263. object>>(data);
  264. string ostInfo = JsonConvert.SerializeObject(dict.Values.First());
  265. return JsonConvert.DeserializeObject<OSTInfo>(ostInfo).camera;
  266. }
  267. else
  268. {
  269. RKLog.Info("====RokidSensorAPI==== USB设备管理模块未初始化!!!");
  270. return null;
  271. }
  272. }
  273. /// <summary>
  274. /// 获取IMUData
  275. /// </summary>
  276. /// <returns></returns>
  277. public IMUData GetIMUData()
  278. {
  279. return imuData;
  280. }
  281. #endregion
  282. }
  283. }