optimze unity project for xr_rm

This commit is contained in:
2026-06-03 14:16:52 +08:00
parent 9260e46b3c
commit 3fc8024648
98 changed files with 20352 additions and 1568 deletions

View File

@ -18,6 +18,8 @@ from xr_rm_interfaces.msg import XrController
class UdpControllerReceiver(Node):
"""将轻量级 XR UDP 数据包转换成 ROS2 左/右手柄消息。"""
_VALID_POSE_SOURCES = {"pxr_predict", "unity_xr", "none"}
def __init__(self) -> None:
super().__init__("udp_controller_receiver")
@ -127,7 +129,20 @@ class UdpControllerReceiver(Node):
msg.header.stamp = self.get_clock().now().to_msg()
msg.header.frame_id = str(payload.get("frame_id", "xr_world"))
msg.hand = hand
msg.grip = self._as_bool(payload.get("grip", payload.get("grip_button", False)))
grip = self._as_bool(payload.get("grip", payload.get("grip_button", False)))
pose_valid = self._optional_bool(payload.get("pose_valid"), default=True)
pose_source = self._validate_pose_diagnostics(payload, hand)
if not pose_valid:
self.get_logger().warn(
f"{hand} XR pose_valid=false强制 grip=false"
f" source={pose_source or 'missing'}"
f" tracking_state={payload.get('tracking_state', 'missing')}"
f" controller_status={payload.get('controller_status', 'missing')}",
throttle_duration_sec=1.0,
)
grip = False
msg.grip = grip
msg.trigger = self._clamp_float(payload.get("trigger", 0.0), 0.0, 1.0)
msg.pose.position.x = float(pos[0])
msg.pose.position.y = float(pos[1])
@ -144,6 +159,30 @@ class UdpControllerReceiver(Node):
msg.pose.orientation.w = float(w)
return msg
def _validate_pose_diagnostics(self, payload: Mapping[str, Any], hand: str) -> str:
has_any_diagnostic = any(
key in payload for key in ("pose_valid", "pose_source", "tracking_state", "controller_status")
)
if has_any_diagnostic and "pose_valid" not in payload:
self.get_logger().warn(
f"{hand} XR 诊断字段缺少 pose_valid按旧协议处理 grip",
throttle_duration_sec=5.0,
)
if has_any_diagnostic and "pose_source" not in payload:
self.get_logger().warn(
f"{hand} XR 诊断字段缺少 pose_source",
throttle_duration_sec=5.0,
)
pose_source_value = payload.get("pose_source", "")
pose_source = str(pose_source_value).strip()
if pose_source and pose_source not in self._VALID_POSE_SOURCES:
self.get_logger().warn(
f"{hand} XR 未知 pose_source={pose_source!r}",
throttle_duration_sec=5.0,
)
return pose_source
@staticmethod
def _contains_pose(payload: Mapping[str, Any]) -> bool:
return any(key in payload for key in ("pos", "position", "p", "pose"))
@ -203,6 +242,12 @@ class UdpControllerReceiver(Node):
return value.lower() in ("1", "true", "yes", "on")
return bool(value)
@classmethod
def _optional_bool(cls, value: Any, default: bool) -> bool:
if value is None:
return default
return cls._as_bool(value)
@staticmethod
def _clamp_float(value: Any, low: float, high: float) -> float:
number = float(value)