dexcontrol 0.2.12__py3-none-any.whl → 0.3.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. dexcontrol/__init__.py +17 -8
  2. dexcontrol/apps/dualsense_teleop_base.py +1 -1
  3. dexcontrol/comm/__init__.py +51 -0
  4. dexcontrol/comm/rtc.py +401 -0
  5. dexcontrol/comm/subscribers.py +329 -0
  6. dexcontrol/config/core/chassis.py +9 -4
  7. dexcontrol/config/core/hand.py +1 -0
  8. dexcontrol/config/sensors/cameras/__init__.py +1 -2
  9. dexcontrol/config/sensors/cameras/zed_camera.py +2 -2
  10. dexcontrol/config/sensors/vega_sensors.py +12 -18
  11. dexcontrol/config/vega.py +4 -1
  12. dexcontrol/core/arm.py +66 -42
  13. dexcontrol/core/chassis.py +142 -120
  14. dexcontrol/core/component.py +107 -58
  15. dexcontrol/core/hand.py +119 -86
  16. dexcontrol/core/head.py +22 -33
  17. dexcontrol/core/misc.py +331 -158
  18. dexcontrol/core/robot_query_interface.py +467 -0
  19. dexcontrol/core/torso.py +5 -9
  20. dexcontrol/robot.py +245 -574
  21. dexcontrol/sensors/__init__.py +1 -2
  22. dexcontrol/sensors/camera/__init__.py +0 -2
  23. dexcontrol/sensors/camera/base_camera.py +150 -0
  24. dexcontrol/sensors/camera/rgb_camera.py +68 -64
  25. dexcontrol/sensors/camera/zed_camera.py +140 -164
  26. dexcontrol/sensors/imu/chassis_imu.py +81 -62
  27. dexcontrol/sensors/imu/zed_imu.py +54 -43
  28. dexcontrol/sensors/lidar/rplidar.py +16 -20
  29. dexcontrol/sensors/manager.py +4 -14
  30. dexcontrol/sensors/ultrasonic.py +15 -28
  31. dexcontrol/utils/__init__.py +0 -11
  32. dexcontrol/utils/comm_helper.py +110 -0
  33. dexcontrol/utils/constants.py +1 -1
  34. dexcontrol/utils/error_code.py +2 -4
  35. dexcontrol/utils/os_utils.py +172 -4
  36. dexcontrol/utils/pb_utils.py +6 -28
  37. {dexcontrol-0.2.12.dist-info → dexcontrol-0.3.4.dist-info}/METADATA +16 -3
  38. dexcontrol-0.3.4.dist-info/RECORD +62 -0
  39. {dexcontrol-0.2.12.dist-info → dexcontrol-0.3.4.dist-info}/WHEEL +1 -1
  40. dexcontrol/config/sensors/cameras/luxonis_camera.py +0 -51
  41. dexcontrol/proto/dexcontrol_msg_pb2.py +0 -73
  42. dexcontrol/proto/dexcontrol_msg_pb2.pyi +0 -220
  43. dexcontrol/proto/dexcontrol_query_pb2.py +0 -77
  44. dexcontrol/proto/dexcontrol_query_pb2.pyi +0 -162
  45. dexcontrol/sensors/camera/luxonis_camera.py +0 -169
  46. dexcontrol/utils/motion_utils.py +0 -199
  47. dexcontrol/utils/rate_limiter.py +0 -172
  48. dexcontrol/utils/rtc_utils.py +0 -144
  49. dexcontrol/utils/subscribers/__init__.py +0 -52
  50. dexcontrol/utils/subscribers/base.py +0 -281
  51. dexcontrol/utils/subscribers/camera.py +0 -332
  52. dexcontrol/utils/subscribers/decoders.py +0 -88
  53. dexcontrol/utils/subscribers/generic.py +0 -110
  54. dexcontrol/utils/subscribers/imu.py +0 -175
  55. dexcontrol/utils/subscribers/lidar.py +0 -172
  56. dexcontrol/utils/subscribers/protobuf.py +0 -111
  57. dexcontrol/utils/subscribers/rtc.py +0 -316
  58. dexcontrol/utils/zenoh_utils.py +0 -122
  59. dexcontrol-0.2.12.dist-info/RECORD +0 -75
  60. {dexcontrol-0.2.12.dist-info → dexcontrol-0.3.4.dist-info}/licenses/LICENSE +0 -0
@@ -8,23 +8,19 @@
8
8
  # 2. Commercial License
9
9
  # For commercial licensing terms, contact: contact@dexmate.ai
10
10
 
11
- """Ultrasonic sensor implementations using Zenoh subscribers.
11
+ """Chassis IMU sensor implementation using DexComm subscribers.
12
12
 
13
- This module provides ultrasonic sensor classes that use the generic
14
- subscriber for distance measurements.
13
+ This module provides IMU sensor class for chassis IMU data
14
+ using DexComm's Raw API.
15
15
  """
16
16
 
17
- from typing import Literal, cast
18
-
19
17
  import numpy as np
20
- import zenoh
21
18
 
22
- from dexcontrol.proto import dexcontrol_msg_pb2
23
- from dexcontrol.utils.subscribers import ProtobufZenohSubscriber
19
+ from dexcontrol.comm import create_imu_subscriber
24
20
 
25
21
 
26
22
  class ChassisIMUSensor:
27
- """Chassis IMU sensor using Zenoh subscriber.
23
+ """Chassis IMU sensor using DexComm subscriber.
28
24
 
29
25
  This sensor provides IMU data from the chassis
30
26
  """
@@ -32,41 +28,34 @@ class ChassisIMUSensor:
32
28
  def __init__(
33
29
  self,
34
30
  configs,
35
- zenoh_session: zenoh.Session,
36
31
  ) -> None:
37
- """Initialize the ultrasonic sensor.
32
+ """Initialize the chassis IMU sensor.
38
33
 
39
34
  Args:
40
- configs: Configuration for the ultrasonic sensor.
41
- zenoh_session: Active Zenoh session for communication.
35
+ configs: Configuration for the chassis IMU sensor.
42
36
  """
43
37
  self._name = configs.name
44
38
 
45
- # Create the generic subscriber with JSON decoder
46
- self._subscriber = ProtobufZenohSubscriber(
39
+ # Create IMU subscriber using DexComm integration
40
+ self._subscriber = create_imu_subscriber(
47
41
  topic=configs.topic,
48
- zenoh_session=zenoh_session,
49
- message_type=dexcontrol_msg_pb2.IMUState,
50
- name=f"{self._name}_subscriber",
51
- enable_fps_tracking=configs.enable_fps_tracking,
52
- fps_log_interval=configs.fps_log_interval,
53
42
  )
54
43
 
55
-
56
44
  def shutdown(self) -> None:
57
- """Shutdown the ultrasonic sensor."""
45
+ """Shutdown the chassis IMU sensor."""
58
46
  self._subscriber.shutdown()
59
47
 
60
48
  def is_active(self) -> bool:
61
- """Check if the ultrasonic sensor is actively receiving data.
49
+ """Check if the chassis IMU sensor is actively receiving data.
62
50
 
63
51
  Returns:
64
52
  True if receiving data, False otherwise.
65
53
  """
66
- return self._subscriber.is_active()
54
+ data = self._subscriber.get_latest()
55
+ return data is not None
67
56
 
68
57
  def wait_for_active(self, timeout: float = 5.0) -> bool:
69
- """Wait for the ultrasonic sensor to start receiving data.
58
+ """Wait for the chassis IMU sensor to start receiving data.
70
59
 
71
60
  Args:
72
61
  timeout: Maximum time to wait in seconds.
@@ -74,80 +63,110 @@ class ChassisIMUSensor:
74
63
  Returns:
75
64
  True if sensor becomes active, False if timeout is reached.
76
65
  """
77
- return self._subscriber.wait_for_active(timeout)
66
+ msg = self._subscriber.wait_for_message(timeout)
67
+ return msg is not None
78
68
 
79
- def get_obs(self, obs_keys: list[Literal['ang_vel', 'acc', 'quat']] | None = None) -> dict[Literal['ang_vel', 'acc', 'quat', 'timestamp_ns'], np.ndarray]:
80
- """Get observation data for the ZED IMU sensor.
69
+ def get_obs(
70
+ self, obs_keys: list[str] | None = None
71
+ ) -> dict[str, np.ndarray] | None:
72
+ """Get observation data for the chassis IMU sensor.
81
73
 
82
74
  Args:
83
75
  obs_keys: List of observation keys to retrieve. If None, returns all available data.
84
- Valid keys: ['ang_vel', 'acc', 'quat']
76
+ Valid keys: ['ang_vel', 'acc', 'quat', 'mag', 'timestamp']
85
77
 
86
78
  Returns:
87
79
  Dictionary with observation data including all IMU measurements.
88
80
  Keys are mapped as follows:
89
- - 'ang_vel': Angular velocity from 'angular_velocity'
90
- - 'acc': Linear acceleration from 'acceleration'
91
- - 'quat': Orientation quaternion from 'orientation', in wxyz convention
81
+ - 'ang_vel': Angular velocity from 'gyro'
82
+ - 'acc': Linear acceleration from 'acc'
83
+ - 'quat': Orientation quaternion from 'quat' [w, x, y, z]
84
+ - 'mag': Magnetometer from 'mag' (if available)
92
85
  - 'timestamp_ns': Timestamp in nanoseconds
93
86
  """
94
87
  if obs_keys is None:
95
- obs_keys = ['ang_vel', 'acc', 'quat']
88
+ obs_keys = ["ang_vel", "acc", "quat"]
96
89
 
97
- data = self._subscriber.get_latest_data()
98
- data = cast(dexcontrol_msg_pb2.IMUState, data)
90
+ data = self._subscriber.get_latest()
99
91
  if data is None:
100
- raise RuntimeError("No IMU data available")
92
+ return None
101
93
 
102
94
  obs_out = {}
103
95
 
96
+ # Add timestamp if available
97
+ if "timestamp" in data:
98
+ obs_out["timestamp_ns"] = data["timestamp"]
99
+
104
100
  for key in obs_keys:
105
- if key == 'ang_vel':
106
- obs_out[key] = np.array([data.gyro_x, data.gyro_y, data.gyro_z])
107
- elif key == 'acc':
108
- obs_out[key] = np.array([data.acc_x, data.acc_y, data.acc_z])
109
- elif key == 'quat':
110
- obs_out[key] = np.array([data.quat_w, data.quat_x, data.quat_y, data.quat_z])
111
- else:
112
- raise ValueError(f"Invalid observation key: {key}")
113
-
114
- if hasattr(data, 'timestamp_ns'):
115
- obs_out['timestamp_ns'] = data.timestamp_ns
101
+ if key == "ang_vel":
102
+ obs_out[key] = data.get("gyro", np.zeros(3))
103
+ elif key == "acc":
104
+ obs_out[key] = data.get("acc", np.zeros(3))
105
+ elif key == "quat":
106
+ obs_out[key] = data.get("quat", np.array([1.0, 0.0, 0.0, 0.0]))
107
+ elif key == "mag" and "mag" in data:
108
+ obs_out[key] = data["mag"]
109
+ elif key == "timestamp" and "timestamp" in data:
110
+ obs_out["timestamp_ns"] = data["timestamp"]
116
111
 
117
112
  return obs_out
118
113
 
119
- def get_acceleration(self) -> np.ndarray:
120
- """Get the latest linear acceleration from ZED IMU.
114
+ def get_acc(self) -> np.ndarray | None:
115
+ """Get the latest linear acceleration from chassis IMU.
121
116
 
122
117
  Returns:
123
118
  Linear acceleration [x, y, z] in m/s² if available, None otherwise.
124
119
  """
125
- return self.get_obs(obs_keys=['acc'])['acc']
120
+ data = self._subscriber.get_latest()
121
+ return data.get("acc") if data else None
126
122
 
127
- def get_angular_velocity(self) -> np.ndarray:
128
- """Get the latest angular velocity from ZED IMU.
123
+ def get_gyro(self) -> np.ndarray | None:
124
+ """Get the latest angular velocity from chassis IMU.
129
125
 
130
126
  Returns:
131
127
  Angular velocity [x, y, z] in rad/s if available, None otherwise.
132
128
  """
133
- return self.get_obs(obs_keys=['ang_vel'])['ang_vel']
129
+ data = self._subscriber.get_latest()
130
+ return data.get("gyro") if data else None
134
131
 
135
- def get_orientation(self) -> np.ndarray:
136
- """Get the latest orientation quaternion from ZED IMU.
132
+ def get_quat(self) -> np.ndarray | None:
133
+ """Get the latest orientation quaternion from chassis IMU.
137
134
 
138
135
  Returns:
139
- Orientation quaternion [x, y, z, w] if available, None otherwise.
136
+ Orientation quaternion [w, x, y, z] if available, None otherwise.
137
+ Note: dexcomm uses [w, x, y, z] quaternion format.
140
138
  """
141
- return self.get_obs(obs_keys=['quat'])['quat']
139
+ data = self._subscriber.get_latest()
140
+ return data.get("quat") if data else None
142
141
 
143
- @property
144
- def fps(self) -> float:
145
- """Get the current FPS measurement.
142
+ def get_mag(self) -> np.ndarray | None:
143
+ """Get the latest magnetometer reading from chassis IMU.
144
+
145
+ Returns:
146
+ Magnetic field [x, y, z] in µT if available, None otherwise.
147
+ """
148
+ data = self._subscriber.get_latest()
149
+ if not data or not isinstance(data, dict):
150
+ return None
151
+ return data.get("mag", None)
152
+
153
+ def has_mag(self) -> bool:
154
+ """Check if the chassis IMU has magnetometer data available.
146
155
 
147
156
  Returns:
148
- Current frames per second measurement.
157
+ True if magnetometer data is available, False otherwise.
149
158
  """
150
- return self._subscriber.fps
159
+ data = self._subscriber.get_latest()
160
+ if not data or not isinstance(data, dict):
161
+ return False
162
+ return "mag" in data and data["mag"] is not None
163
+
164
+ # Backward compatibility aliases
165
+ get_acceleration = get_acc
166
+ get_angular_velocity = get_gyro
167
+ get_orientation = get_quat
168
+ get_magnetometer = get_mag
169
+ has_magnetometer = has_mag
151
170
 
152
171
  @property
153
172
  def name(self) -> str:
@@ -11,9 +11,8 @@
11
11
  """ZED IMU sensor implementation using Zenoh subscriber."""
12
12
 
13
13
  import numpy as np
14
- import zenoh
15
14
 
16
- from dexcontrol.utils.subscribers.imu import IMUSubscriber
15
+ from dexcontrol.comm import create_imu_subscriber
17
16
 
18
17
 
19
18
  class ZedIMUSensor:
@@ -28,23 +27,17 @@ class ZedIMUSensor:
28
27
  def __init__(
29
28
  self,
30
29
  configs,
31
- zenoh_session: zenoh.Session,
32
30
  ) -> None:
33
31
  """Initialize the ZED IMU sensor.
34
32
 
35
33
  Args:
36
34
  configs: Configuration object containing topic, name, and other settings.
37
- zenoh_session: Active Zenoh session for communication.
38
35
  """
39
36
  self._name = configs.name
40
37
 
41
- # Create the IMU subscriber
42
- self._subscriber = IMUSubscriber(
38
+
39
+ self._subscriber = create_imu_subscriber(
43
40
  topic=configs.topic,
44
- zenoh_session=zenoh_session,
45
- name=f"{self._name}_subscriber",
46
- enable_fps_tracking=configs.enable_fps_tracking,
47
- fps_log_interval=configs.fps_log_interval,
48
41
  )
49
42
 
50
43
  def shutdown(self) -> None:
@@ -57,7 +50,8 @@ class ZedIMUSensor:
57
50
  Returns:
58
51
  True if receiving data, False otherwise.
59
52
  """
60
- return self._subscriber.is_active()
53
+ data = self._subscriber.get_latest()
54
+ return data is not None
61
55
 
62
56
  def wait_for_active(self, timeout: float = 5.0) -> bool:
63
57
  """Wait for the ZED IMU sensor to start receiving data.
@@ -68,92 +62,109 @@ class ZedIMUSensor:
68
62
  Returns:
69
63
  True if sensor becomes active, False if timeout is reached.
70
64
  """
71
- return self._subscriber.wait_for_active(timeout)
65
+ msg = self._subscriber.wait_for_message(timeout)
66
+ return msg is not None
72
67
 
73
68
  def get_obs(self, obs_keys: list[str] | None = None) -> dict[str, np.ndarray] | None:
74
69
  """Get observation data for the ZED IMU sensor.
75
70
 
76
71
  Args:
77
72
  obs_keys: List of observation keys to retrieve. If None, returns all available data.
78
- Valid keys: ['ang_vel', 'acc', 'quat', 'timestamp']
73
+ Valid keys: ['ang_vel', 'acc', 'quat', 'mag', 'timestamp']
79
74
 
80
75
  Returns:
81
76
  Dictionary with observation data including all IMU measurements.
82
77
  Keys are mapped as follows:
83
- - 'ang_vel': Angular velocity from 'angular_velocity'
84
- - 'acc': Linear acceleration from 'acceleration'
85
- - 'quat': Orientation quaternion from 'orientation'
78
+ - 'ang_vel': Angular velocity from 'gyro'
79
+ - 'acc': Linear acceleration from 'acc'
80
+ - 'quat': Orientation quaternion from 'quat'
81
+ - 'mag': Magnetometer from 'mag' (if available)
86
82
  - 'timestamp_ns': Timestamp from 'timestamp'
87
83
  """
88
84
  if obs_keys is None:
89
85
  obs_keys = ['ang_vel', 'acc', 'quat']
90
86
 
91
- data = self._subscriber.get_latest_data()
87
+ data = self._subscriber.get_latest()
92
88
  if data is None:
93
89
  return None
94
90
 
95
- obs_out = {'timestamp_ns': data['timestamp']}
91
+ obs_out = {}
92
+
93
+ # Add timestamp if available
94
+ if 'timestamp' in data:
95
+ obs_out['timestamp_ns'] = data['timestamp']
96
96
 
97
97
  for key in obs_keys:
98
98
  if key == 'ang_vel':
99
- obs_out[key] = data['angular_velocity']
99
+ obs_out[key] = data.get('gyro', np.zeros(3))
100
100
  elif key == 'acc':
101
- obs_out[key] = data['acceleration']
101
+ obs_out[key] = data.get('acc', np.zeros(3))
102
102
  elif key == 'quat':
103
- obs_out[key] = data['orientation']
104
- else:
105
- raise ValueError(f"Invalid observation key: {key}")
103
+ obs_out[key] = data.get('quat', np.array([1.0, 0.0, 0.0, 0.0]))
104
+ elif key == 'mag' and 'mag' in data:
105
+ obs_out[key] = data['mag']
106
+ elif key == 'timestamp' and 'timestamp' in data:
107
+ obs_out['timestamp_ns'] = data['timestamp']
106
108
 
107
109
  return obs_out
108
110
 
109
- def get_acceleration(self) -> np.ndarray | None:
111
+ def get_acc(self) -> np.ndarray | None:
110
112
  """Get the latest linear acceleration from ZED IMU.
111
113
 
112
114
  Returns:
113
115
  Linear acceleration [x, y, z] in m/s² if available, None otherwise.
114
116
  """
115
- return self._subscriber.get_acceleration()
117
+ data = self._subscriber.get_latest()
118
+ return data.get('acc') if data else None
116
119
 
117
- def get_angular_velocity(self) -> np.ndarray | None:
120
+ def get_gyro(self) -> np.ndarray | None:
118
121
  """Get the latest angular velocity from ZED IMU.
119
122
 
120
123
  Returns:
121
124
  Angular velocity [x, y, z] in rad/s if available, None otherwise.
122
125
  """
123
- return self._subscriber.get_angular_velocity()
126
+ data = self._subscriber.get_latest()
127
+ return data.get('gyro') if data else None
124
128
 
125
- def get_orientation(self) -> np.ndarray | None:
129
+ def get_quat(self) -> np.ndarray | None:
126
130
  """Get the latest orientation quaternion from ZED IMU.
127
131
 
128
132
  Returns:
129
- Orientation quaternion [x, y, z, w] if available, None otherwise.
133
+ Orientation quaternion [w, x, y, z] if available, None otherwise.
134
+ Note: dexcomm uses [w, x, y, z] quaternion format.
130
135
  """
131
- return self._subscriber.get_orientation()
136
+ data = self._subscriber.get_latest()
137
+ return data.get('quat') if data else None
132
138
 
133
- def get_magnetometer(self) -> np.ndarray | None:
139
+ def get_mag(self) -> np.ndarray | None:
134
140
  """Get the latest magnetometer reading from ZED IMU.
135
141
 
136
142
  Returns:
137
143
  Magnetic field [x, y, z] in µT if available, None otherwise.
138
144
  """
139
- return self._subscriber.get_magnetometer()
145
+ data = self._subscriber.get_latest()
146
+ if not data or not isinstance(data, dict):
147
+ return None
148
+ return data.get('mag', None)
140
149
 
141
- def has_magnetometer(self) -> bool:
150
+ def has_mag(self) -> bool:
142
151
  """Check if the ZED IMU has magnetometer data available.
143
152
 
144
153
  Returns:
145
154
  True if magnetometer data is available, False otherwise.
146
155
  """
147
- return self._subscriber.has_magnetometer()
148
-
149
- @property
150
- def fps(self) -> float:
151
- """Get the current FPS measurement.
152
-
153
- Returns:
154
- Current frames per second measurement.
155
- """
156
- return self._subscriber.fps
156
+ data = self._subscriber.get_latest()
157
+ if not data or not isinstance(data, dict):
158
+ return False
159
+ return 'mag' in data and data['mag'] is not None
160
+
161
+
162
+ # Backward compatibility aliases
163
+ get_acceleration = get_acc
164
+ get_angular_velocity = get_gyro
165
+ get_orientation = get_quat
166
+ get_magnetometer = get_mag
167
+ has_magnetometer = has_mag
157
168
 
158
169
  @property
159
170
  def name(self) -> str:
@@ -17,9 +17,8 @@ subscriber for scan data.
17
17
  from typing import Any
18
18
 
19
19
  import numpy as np
20
- import zenoh
21
20
 
22
- from dexcontrol.utils.subscribers.lidar import LidarSubscriber
21
+ from dexcontrol.comm import create_lidar_subscriber
23
22
 
24
23
 
25
24
  class RPLidarSensor:
@@ -32,26 +31,17 @@ class RPLidarSensor:
32
31
  def __init__(
33
32
  self,
34
33
  configs,
35
- zenoh_session: zenoh.Session,
36
34
  ) -> None:
37
35
  """Initialize the LIDAR sensor.
38
36
 
39
37
  Args:
40
- topic: Zenoh topic to subscribe to for LIDAR data.
41
- zenoh_session: Active Zenoh session for communication.
42
- name: Name for the sensor instance.
43
- enable_fps_tracking: Whether to track and log FPS metrics.
44
- fps_log_interval: Number of frames between FPS calculations.
38
+ configs: Configuration for the LIDAR sensor.
45
39
  """
46
40
  self._name = configs.name
47
41
 
48
42
  # Create the LIDAR subscriber
49
- self._subscriber = LidarSubscriber(
50
- topic=configs.topic,
51
- zenoh_session=zenoh_session,
52
- name=f"{self._name}_subscriber",
53
- enable_fps_tracking=configs.enable_fps_tracking,
54
- fps_log_interval=configs.fps_log_interval,
43
+ self._subscriber = create_lidar_subscriber(
44
+ topic=configs.topic
55
45
  )
56
46
 
57
47
 
@@ -65,7 +55,8 @@ class RPLidarSensor:
65
55
  Returns:
66
56
  True if receiving data, False otherwise.
67
57
  """
68
- return self._subscriber.is_active()
58
+ data = self._subscriber.get_latest()
59
+ return data is not None
69
60
 
70
61
  def wait_for_active(self, timeout: float = 5.0) -> bool:
71
62
  """Wait for the LIDAR sensor to start receiving data.
@@ -76,7 +67,8 @@ class RPLidarSensor:
76
67
  Returns:
77
68
  True if sensor becomes active, False if timeout is reached.
78
69
  """
79
- return self._subscriber.wait_for_active(timeout)
70
+ msg = self._subscriber.wait_for_message(timeout)
71
+ return msg is not None
80
72
 
81
73
  def get_obs(self) -> dict[str, Any] | None:
82
74
  """Get the latest LIDAR scan data.
@@ -89,7 +81,8 @@ class RPLidarSensor:
89
81
  - qualities: Array of quality values (0-255) if available, None otherwise
90
82
  - timestamp: Timestamp in nanoseconds (int)
91
83
  """
92
- return self._subscriber.get_latest_data()
84
+ data = self._subscriber.get_latest()
85
+ return data
93
86
 
94
87
  def get_ranges(self) -> np.ndarray | None:
95
88
  """Get the latest range measurements.
@@ -97,7 +90,8 @@ class RPLidarSensor:
97
90
  Returns:
98
91
  Array of range measurements in meters if available, None otherwise.
99
92
  """
100
- return self._subscriber.get_ranges()
93
+ data = self._subscriber.get_latest()
94
+ return data.ranges if data else None
101
95
 
102
96
  def get_angles(self) -> np.ndarray | None:
103
97
  """Get the latest angle measurements.
@@ -105,7 +99,8 @@ class RPLidarSensor:
105
99
  Returns:
106
100
  Array of angle measurements in radians if available, None otherwise.
107
101
  """
108
- return self._subscriber.get_angles()
102
+ data = self._subscriber.get_latest()
103
+ return data.angles if data else None
109
104
 
110
105
  def get_qualities(self) -> np.ndarray | None:
111
106
  """Get the latest quality measurements.
@@ -113,7 +108,8 @@ class RPLidarSensor:
113
108
  Returns:
114
109
  Array of quality values (0-255) if available, None otherwise.
115
110
  """
116
- return self._subscriber.get_qualities()
111
+ data = self._subscriber.get_latest()
112
+ return data.qualities if data else None
117
113
 
118
114
  def get_point_count(self) -> int:
119
115
  """Get the number of points in the latest scan.
@@ -8,7 +8,7 @@
8
8
  # 2. Commercial License
9
9
  # For commercial licensing terms, contact: contact@dexmate.ai
10
10
 
11
- """Sensor manager for managing robot sensors with Zenoh communication.
11
+ """Sensor manager for managing robot sensors.
12
12
 
13
13
  This module provides the Sensors class that manages multiple sensor instances
14
14
  based on configuration and provides unified access to them.
@@ -19,14 +19,12 @@ import traceback
19
19
  from typing import TYPE_CHECKING, Any
20
20
 
21
21
  import hydra.utils as hydra_utils
22
- import zenoh
23
22
  from loguru import logger
24
23
  from omegaconf import DictConfig, OmegaConf
25
24
 
26
25
  from dexcontrol.config.sensors.vega_sensors import VegaSensorsConfig
27
26
 
28
27
  if TYPE_CHECKING:
29
- from dexcontrol.sensors.camera.luxonis_camera import LuxonisCameraSensor
30
28
  from dexcontrol.sensors.camera.rgb_camera import RGBCameraSensor
31
29
  from dexcontrol.sensors.camera.zed_camera import ZedCameraSensor
32
30
  from dexcontrol.sensors.imu.chassis_imu import ChassisIMUSensor
@@ -44,14 +42,11 @@ class Sensors:
44
42
 
45
43
  Attributes:
46
44
  _sensors: List of instantiated sensor objects.
47
- _zenoh_session: Active Zenoh session for communication.
48
45
  """
49
46
 
50
47
  if TYPE_CHECKING:
51
48
  # Type annotations for dynamically created sensor attributes
52
49
  head_camera: ZedCameraSensor
53
- left_wrist_camera: LuxonisCameraSensor
54
- right_wrist_camera: LuxonisCameraSensor
55
50
  base_left_camera: RGBCameraSensor
56
51
  base_right_camera: RGBCameraSensor
57
52
  base_front_camera: RGBCameraSensor
@@ -61,16 +56,13 @@ class Sensors:
61
56
  lidar: RPLidarSensor
62
57
  ultrasonic: UltrasonicSensor
63
58
 
64
- def __init__(self, configs: DictConfig | VegaSensorsConfig,
65
- zenoh_session: zenoh.Session) -> None:
59
+ def __init__(self, configs: DictConfig | VegaSensorsConfig) -> None:
66
60
  """Initialize sensors from configuration.
67
61
 
68
62
  Args:
69
63
  configs: Configuration for all sensors (VegaSensorsConfig or DictConfig).
70
- zenoh_session: Active Zenoh session for communication.
71
64
  """
72
65
  self._sensors: list[Any] = []
73
- self._zenoh_session = zenoh_session
74
66
 
75
67
  dict_configs = (OmegaConf.structured(configs) if isinstance(configs, VegaSensorsConfig)
76
68
  else configs)
@@ -108,10 +100,8 @@ class Sensors:
108
100
  'configs': {k: v for k, v in config.items() if k != '_target_'}
109
101
  })
110
102
 
111
- sensor = hydra_utils.instantiate(
112
- temp_config,
113
- zenoh_session=self._zenoh_session,
114
- )
103
+ # Note: zenoh_session no longer needed as DexComm handles sessions
104
+ sensor = hydra_utils.instantiate(temp_config)
115
105
 
116
106
  if hasattr(sensor, "start"):
117
107
  sensor.start()