RomaSceneBootstrap.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. using LightGlue.Unity.Networking;
  2. using LightGlue.Unity.Python;
  3. using UnityEngine;
  4. namespace LightGlue.Unity.Roma
  5. {
  6. /// <summary>
  7. /// Roma 新场景一键启动器:
  8. /// - 启动广播发现
  9. /// - 发现后配置 WiFi 图传并开启
  10. /// - 启动 Roma Python(独立于 LightGlue_Deployment)
  11. /// - 启动图像显示与结果接收(复用 UDPResultReceiver 协议/端口)
  12. ///
  13. /// 约束:该脚本只应挂在 Roma 新场景中;用户不会同时运行旧场景与新场景。
  14. /// </summary>
  15. public sealed class RomaSceneBootstrap : MonoBehaviour
  16. {
  17. [Header("Discovery + Control")]
  18. public RomaDeviceDiscoveryListener discovery;
  19. public RomaWifiCameraControlClient wifiControl;
  20. [Header("Python (RoMa)")]
  21. [Tooltip("Roma 专用 Python 进程控制器(需指向 LightGlue_Roma 工程目录与脚本)")]
  22. public PythonProcessController romaPythonController;
  23. [Header("Image Viewer (Python -> Unity)")]
  24. public RomaForwardedImageViewer forwardedViewer;
  25. [Header("Result Receiver (Python -> Unity)")]
  26. [Tooltip("复用现有 UDPResultReceiver 协议(0x0001/20字节),监听 pythonResultPort=12348(可在 Inspector 改)")]
  27. public bool enableResultReceiver = true;
  28. public string resultBindIp = "127.0.0.1";
  29. public int resultPort = 12348;
  30. public int maxResultQueueSize = 10;
  31. public UDPResultReceiver ResultReceiver => _resultReceiver;
  32. private UDPResultReceiver _resultReceiver;
  33. private void OnEnable()
  34. {
  35. // 如果已存在持久化 RomaManager,则不再在场景里重复启动/绑定端口
  36. if (RomaManager.Instance != null)
  37. {
  38. enabled = false;
  39. return;
  40. }
  41. Application.runInBackground = true;
  42. if (discovery == null) discovery = FindObjectOfType<RomaDeviceDiscoveryListener>();
  43. if (wifiControl == null) wifiControl = FindObjectOfType<RomaWifiCameraControlClient>();
  44. if (forwardedViewer == null) forwardedViewer = FindObjectOfType<RomaForwardedImageViewer>();
  45. if (wifiControl != null && discovery != null)
  46. wifiControl.BindDiscovery(discovery);
  47. if (discovery != null && !discovery.IsListening)
  48. discovery.StartListening();
  49. // 启动 Roma Python:这里不改旧工程逻辑,只调用 StartPython(Roma 控制器需在 Inspector 配好路径/脚本)
  50. if (romaPythonController != null && !romaPythonController.IsRunning)
  51. romaPythonController.StartPython();
  52. if (enableResultReceiver)
  53. {
  54. try
  55. {
  56. _resultReceiver = new UDPResultReceiver(resultBindIp, resultPort, maxResultQueueSize);
  57. _resultReceiver.Start();
  58. }
  59. catch (System.Exception ex)
  60. {
  61. Debug.LogError($"[RomaBootstrap] Start result receiver failed on {resultBindIp}:{resultPort}: {ex.Message}");
  62. try { _resultReceiver?.Stop(); } catch { /* ignore */ }
  63. _resultReceiver = null;
  64. }
  65. }
  66. }
  67. private void OnDisable()
  68. {
  69. try { _resultReceiver?.Stop(); } catch { /* ignore */ }
  70. _resultReceiver = null;
  71. }
  72. /// <summary>
  73. /// Roma 场景侧提供一个“取最新结果”的便捷接口(与 Bridge.TryGetLatestResult 风格一致)。
  74. /// </summary>
  75. public bool TryGetLatestResult(out LightGlueResult result)
  76. {
  77. result = default(LightGlueResult);
  78. if (_resultReceiver == null) return false;
  79. bool any = false;
  80. while (_resultReceiver.TryDequeueResult(out var r))
  81. {
  82. result = r;
  83. any = true;
  84. }
  85. return any;
  86. }
  87. }
  88. }