dexcontrol 0.2.10__py3-none-any.whl → 0.3.0__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.

Potentially problematic release.


This version of dexcontrol might be problematic. Click here for more details.

Files changed (47) hide show
  1. dexcontrol/__init__.py +2 -0
  2. dexcontrol/config/core/arm.py +5 -1
  3. dexcontrol/config/core/chassis.py +9 -4
  4. dexcontrol/config/core/hand.py +2 -1
  5. dexcontrol/config/core/head.py +7 -8
  6. dexcontrol/config/core/misc.py +14 -1
  7. dexcontrol/config/core/torso.py +8 -4
  8. dexcontrol/config/sensors/cameras/__init__.py +2 -1
  9. dexcontrol/config/sensors/cameras/luxonis_camera.py +51 -0
  10. dexcontrol/config/sensors/cameras/rgb_camera.py +1 -1
  11. dexcontrol/config/sensors/cameras/zed_camera.py +2 -2
  12. dexcontrol/config/sensors/vega_sensors.py +9 -1
  13. dexcontrol/config/vega.py +34 -3
  14. dexcontrol/core/arm.py +103 -58
  15. dexcontrol/core/chassis.py +146 -115
  16. dexcontrol/core/component.py +83 -20
  17. dexcontrol/core/hand.py +74 -39
  18. dexcontrol/core/head.py +41 -28
  19. dexcontrol/core/misc.py +256 -25
  20. dexcontrol/core/robot_query_interface.py +440 -0
  21. dexcontrol/core/torso.py +28 -10
  22. dexcontrol/proto/dexcontrol_msg_pb2.py +27 -37
  23. dexcontrol/proto/dexcontrol_msg_pb2.pyi +111 -126
  24. dexcontrol/proto/dexcontrol_query_pb2.py +39 -35
  25. dexcontrol/proto/dexcontrol_query_pb2.pyi +41 -4
  26. dexcontrol/robot.py +266 -409
  27. dexcontrol/sensors/__init__.py +2 -1
  28. dexcontrol/sensors/camera/__init__.py +2 -0
  29. dexcontrol/sensors/camera/luxonis_camera.py +169 -0
  30. dexcontrol/sensors/camera/zed_camera.py +17 -8
  31. dexcontrol/sensors/imu/chassis_imu.py +5 -1
  32. dexcontrol/sensors/imu/zed_imu.py +3 -2
  33. dexcontrol/sensors/lidar/rplidar.py +1 -0
  34. dexcontrol/sensors/manager.py +3 -0
  35. dexcontrol/utils/constants.py +3 -0
  36. dexcontrol/utils/error_code.py +236 -0
  37. dexcontrol/utils/os_utils.py +183 -1
  38. dexcontrol/utils/pb_utils.py +0 -22
  39. dexcontrol/utils/subscribers/lidar.py +1 -0
  40. dexcontrol/utils/trajectory_utils.py +17 -5
  41. dexcontrol/utils/viz_utils.py +86 -11
  42. dexcontrol/utils/zenoh_utils.py +288 -2
  43. {dexcontrol-0.2.10.dist-info → dexcontrol-0.3.0.dist-info}/METADATA +15 -2
  44. dexcontrol-0.3.0.dist-info/RECORD +76 -0
  45. dexcontrol-0.2.10.dist-info/RECORD +0 -72
  46. {dexcontrol-0.2.10.dist-info → dexcontrol-0.3.0.dist-info}/WHEEL +0 -0
  47. {dexcontrol-0.2.10.dist-info → dexcontrol-0.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,440 @@
1
+ # Copyright (C) 2025 Dexmate Inc.
2
+ #
3
+ # This software is dual-licensed:
4
+ #
5
+ # 1. GNU Affero General Public License v3.0 (AGPL-3.0)
6
+ # See LICENSE-AGPL for details
7
+ #
8
+ # 2. Commercial License
9
+ # For commercial licensing terms, contact: contact@dexmate.ai
10
+
11
+ """Zenoh query utilities for robot communication.
12
+
13
+ This module provides the ZenohQueryable class that encapsulates all zenoh-based
14
+ queries and communication with the robot server. It handles various query types
15
+ including hand type detection, version information, status queries, and control operations.
16
+ """
17
+
18
+ import json
19
+ import time
20
+ from typing import TYPE_CHECKING, Any, Literal, cast
21
+
22
+ import zenoh
23
+ from loguru import logger
24
+
25
+ from dexcontrol.config.vega import VegaConfig, get_vega_config
26
+ from dexcontrol.core.hand import HandType
27
+ from dexcontrol.proto import dexcontrol_query_pb2
28
+ from dexcontrol.utils.os_utils import resolve_key_name
29
+ from dexcontrol.utils.pb_utils import (
30
+ ComponentStatus,
31
+ status_to_dict,
32
+ )
33
+ from dexcontrol.utils.viz_utils import show_component_status
34
+ from dexcontrol.utils.zenoh_utils import compute_ntp_stats, create_zenoh_session
35
+
36
+ if TYPE_CHECKING:
37
+ from dexcontrol.config.vega import VegaConfig
38
+
39
+
40
+ class RobotQueryInterface:
41
+ """Base class for zenoh query operations.
42
+
43
+ This class provides a clean interface for all zenoh-based queries and
44
+ communication operations. It maintains references to the zenoh session
45
+ and configuration needed for queries.
46
+
47
+ Can be used as a context manager for automatic resource cleanup:
48
+ >>> with RobotQueryInterface.create() as interface:
49
+ ... version_info = interface.get_version_info()
50
+ """
51
+
52
+ def __init__(self, zenoh_session: zenoh.Session, configs: "VegaConfig"):
53
+ """Initialize the RobotQueryInterface with session and config.
54
+
55
+ Args:
56
+ zenoh_session: Active zenoh session for communication.
57
+ configs: Robot configuration containing query names.
58
+ """
59
+ self._zenoh_session: zenoh.Session = zenoh_session
60
+ self._configs = configs
61
+ self._owns_session = False
62
+
63
+ @classmethod
64
+ def create(
65
+ cls,
66
+ zenoh_config_file: str | None = None,
67
+ ) -> "RobotQueryInterface":
68
+ """Create a standalone RobotQueryInterface with its own zenoh session.
69
+
70
+ This class method provides a convenient way to create a RobotQueryInterface
71
+ without requiring the full Robot class. The created interface will manage
72
+ its own zenoh session and configuration.
73
+
74
+ Args:
75
+ zenoh_config_file: Path to zenoh configuration file. If None,
76
+ uses the default configuration path.
77
+ robot_config_path: Path to robot configuration file. If None,
78
+ uses default configuration for detected robot model.
79
+
80
+ Returns:
81
+ RobotQueryInterface instance ready for use.
82
+
83
+ Raises:
84
+ RuntimeError: If zenoh session initialization fails.
85
+ ValueError: If robot configuration cannot be loaded.
86
+
87
+ Example:
88
+ >>> query_interface = RobotQueryInterface.create_standalone()
89
+ >>> version_info = query_interface.get_version_info()
90
+ >>> query_interface.close()
91
+ """
92
+
93
+ session = create_zenoh_session(zenoh_config_file)
94
+ config: VegaConfig = get_vega_config()
95
+
96
+ instance = cls(session, config)
97
+ instance._owns_session = True
98
+ return instance
99
+
100
+ def close(self) -> None:
101
+ """Close the zenoh session if owned by this instance.
102
+
103
+ This method should be called when done using a standalone
104
+ RobotQueryInterface to properly clean up resources.
105
+ """
106
+ if self._owns_session and self._zenoh_session:
107
+ logger.debug("Closing zenoh session")
108
+ self._zenoh_session.close()
109
+
110
+ def __enter__(self) -> "RobotQueryInterface":
111
+ """Enter context manager."""
112
+ return self
113
+
114
+ def __exit__(self, exc_type, exc_val, exc_tb) -> None:
115
+ """Exit context manager and clean up resources."""
116
+ self.close()
117
+
118
+ def query_hand_type(self) -> dict[str, HandType]:
119
+ """Query the hand type information from the server.
120
+
121
+ Returns:
122
+ Dictionary containing hand type information for left and right hands.
123
+ Format: {"left": hand_type_name, "right": hand_type_name}
124
+ Possible hand types: "UNKNOWN", "HandF5D6_V1", "HandF5D6_V2"
125
+ UNKNOWN means not connected or unknown end effector connected.
126
+
127
+ Raises:
128
+ RuntimeError: If hand type information cannot be retrieved.
129
+ """
130
+ try:
131
+ # Sleep more time to avoice zenoh query timeout
132
+ time.sleep(2)
133
+ replies = self._zenoh_session.get(
134
+ resolve_key_name(self._configs.hand_info_query_name), timeout=5.0
135
+ )
136
+
137
+ for reply in replies:
138
+ if reply.ok and reply.ok.payload:
139
+ # Parse JSON response (not protobuf)
140
+ payload_bytes = reply.ok.payload.to_bytes()
141
+ payload_str = payload_bytes.decode("utf-8")
142
+ hand_info = json.loads(payload_str)
143
+
144
+ # Validate the expected format
145
+ if isinstance(hand_info, dict):
146
+ logger.info(f"End effector hand types: {hand_info}")
147
+ return {
148
+ "left": HandType(hand_info["left"]),
149
+ "right": HandType(hand_info["right"]),
150
+ }
151
+ else:
152
+ logger.warning(
153
+ f"Invalid hand type format received: {hand_info}"
154
+ )
155
+
156
+ # If no valid response received, assume v1 for backward compatibility
157
+ return {"left": HandType.HandF5D6_V1, "right": HandType.HandF5D6_V1}
158
+
159
+ except Exception as e:
160
+ logger.warning(f"Failed to query hand type: {e}. Assuming v1 hand types.")
161
+ return {"left": HandType.HandF5D6_V1, "right": HandType.HandF5D6_V1}
162
+
163
+ def query_ntp(
164
+ self,
165
+ sample_count: int = 30,
166
+ show: bool = False,
167
+ timeout: float = 1.0,
168
+ device: Literal["soc", "jetson"] = "soc",
169
+ ) -> dict[Literal["success", "offset", "rtt"], bool | float]:
170
+ """Query the NTP server via zenoh for time synchronization and compute robust statistics.
171
+
172
+ Args:
173
+ sample_count: Number of NTP samples to request (default: 50).
174
+ show: Whether to print summary statistics using a rich table.
175
+ timeout: Timeout for the zenoh querier in seconds (default: 2.0).
176
+ device: Which device to query for NTP ("soc" or "jetson").
177
+
178
+ Returns:
179
+ Dictionary with keys:
180
+ - "success": True if any replies were received, False otherwise.
181
+ - "offset": Mean offset (in seconds) after removing RTT outliers.
182
+ - "rtt": Mean round-trip time (in seconds) after removing RTT outliers.
183
+ """
184
+ if device == "soc":
185
+ ntp_key = resolve_key_name(self._configs.soc_ntp_query_name)
186
+ elif device == "jetson":
187
+ raise NotImplementedError("Jetson NTP query is not implemented yet")
188
+
189
+ time_offset = []
190
+ time_rtt = []
191
+
192
+ querier = self._zenoh_session.declare_querier(ntp_key, timeout=timeout)
193
+ time.sleep(0.1)
194
+
195
+ reply_count = 0
196
+ for i in range(sample_count):
197
+ request = dexcontrol_query_pb2.NTPRequest()
198
+ request.client_send_time_ns = time.time_ns()
199
+ request.sample_count = sample_count
200
+ request.sample_index = i
201
+ replies = querier.get(payload=request.SerializeToString())
202
+
203
+ for reply in replies:
204
+ reply_count += 1
205
+ if reply.ok and reply.ok.payload:
206
+ client_receive_time_ns = time.time_ns()
207
+ response = dexcontrol_query_pb2.NTPResponse()
208
+ response.ParseFromString(reply.ok.payload.to_bytes())
209
+ t0 = request.client_send_time_ns
210
+ t1 = response.server_receive_time_ns
211
+ t2 = response.server_send_time_ns
212
+ t3 = client_receive_time_ns
213
+ offset = ((t1 - t0) + (t2 - t3)) // 2 / 1e9
214
+ rtt = (t3 - t0) / 1e9
215
+ time_offset.append(offset)
216
+ time_rtt.append(rtt)
217
+ if i < sample_count - 1:
218
+ time.sleep(0.01)
219
+
220
+ querier.undeclare()
221
+ if reply_count == 0:
222
+ return {"success": False, "offset": 0, "rtt": 0}
223
+
224
+ stats = compute_ntp_stats(time_offset, time_rtt)
225
+ offset = stats["offset (mean)"]
226
+ rtt = stats["round_trip_time (mean)"]
227
+ if show:
228
+ from dexcontrol.utils.viz_utils import show_ntp_stats
229
+
230
+ show_ntp_stats(stats)
231
+
232
+ return {"success": True, "offset": offset, "rtt": rtt}
233
+
234
+ def get_version_info(self, show: bool = True) -> dict[str, Any]:
235
+ """Retrieve comprehensive version information using JSON interface.
236
+
237
+ This method queries the new JSON-based version endpoint that provides:
238
+ - Server component versions (hardware, software, compile_time, hashes)
239
+ - Minimum required client version
240
+ - Version compatibility information
241
+
242
+ Args:
243
+ show: Whether to display the version information.
244
+
245
+ Returns:
246
+ Dictionary containing comprehensive version information with structure:
247
+ {
248
+ "server": {
249
+ "component_name": {
250
+ "hardware_version": int,
251
+ "software_version": int,
252
+ "compile_time": str,
253
+ "main_hash": str,
254
+ "sub_hash": str
255
+ }
256
+ },
257
+ "client": {
258
+ "minimal_version": str
259
+ }
260
+ }
261
+
262
+ Raises:
263
+ RuntimeError: If version information cannot be retrieved.
264
+ """
265
+ try:
266
+ replies = self._zenoh_session.get(
267
+ resolve_key_name(self._configs.version_info_name), timeout=5.0
268
+ )
269
+
270
+ for reply in replies:
271
+ if reply.ok and reply.ok.payload:
272
+ try:
273
+ # Parse JSON response
274
+ payload_bytes = reply.ok.payload.to_bytes()
275
+ payload_str = payload_bytes.decode("utf-8")
276
+ version_info = json.loads(payload_str)
277
+
278
+ # Validate expected structure
279
+ if (
280
+ isinstance(version_info, dict)
281
+ and "server" in version_info
282
+ and "client" in version_info
283
+ ):
284
+ if show:
285
+ self._show_version_info(version_info)
286
+ return version_info
287
+ else:
288
+ logger.warning(
289
+ f"Invalid version info format received: {version_info}"
290
+ )
291
+ except (json.JSONDecodeError, UnicodeDecodeError) as e:
292
+ logger.warning(f"Failed to parse version info response: {e}")
293
+ continue
294
+
295
+ raise RuntimeError("No valid version information received from server")
296
+
297
+ except Exception as e:
298
+ raise RuntimeError(f"Failed to retrieve version information: {e}") from e
299
+
300
+ def get_component_status(
301
+ self, show: bool = True
302
+ ) -> dict[str, dict[str, bool | ComponentStatus]]:
303
+ """Retrieve status information for all components.
304
+
305
+ Args:
306
+ show: Whether to display the status information.
307
+
308
+ Returns:
309
+ Dictionary containing status information for all components.
310
+
311
+ Raises:
312
+ RuntimeError: If status information cannot be retrieved.
313
+ """
314
+ try:
315
+ replies = self._zenoh_session.get(
316
+ resolve_key_name(self._configs.status_info_name)
317
+ )
318
+ status_dict = {}
319
+ for reply in replies:
320
+ if reply.ok and reply.ok.payload:
321
+ status_bytes = reply.ok.payload.to_bytes()
322
+ status_msg = cast(
323
+ dexcontrol_query_pb2.ComponentStates,
324
+ dexcontrol_query_pb2.ComponentStates.FromString(status_bytes),
325
+ )
326
+ status_dict = status_to_dict(status_msg)
327
+ break
328
+
329
+ if show:
330
+ show_component_status(status_dict)
331
+ return status_dict
332
+ except Exception as e:
333
+ raise RuntimeError(f"Failed to retrieve component status: {e}") from e
334
+
335
+ def reboot_component(
336
+ self,
337
+ part: Literal["arm", "chassis", "torso"],
338
+ ) -> None:
339
+ """Reboot a specific robot component.
340
+
341
+ Args:
342
+ part: Component to reboot ("arm", "chassis", or "torso").
343
+
344
+ Raises:
345
+ ValueError: If the specified component is invalid.
346
+ RuntimeError: If the reboot operation fails.
347
+ """
348
+ component_map = {
349
+ "arm": dexcontrol_query_pb2.RebootComponent.Component.ARM,
350
+ "chassis": dexcontrol_query_pb2.RebootComponent.Component.CHASSIS,
351
+ "torso": dexcontrol_query_pb2.RebootComponent.Component.TORSO,
352
+ }
353
+
354
+ if part not in component_map:
355
+ raise ValueError(f"Invalid component: {part}")
356
+
357
+ try:
358
+ query_msg = dexcontrol_query_pb2.RebootComponent(
359
+ component=component_map[part]
360
+ )
361
+ self._zenoh_session.get(
362
+ resolve_key_name(self._configs.reboot_query_name),
363
+ payload=query_msg.SerializeToString(),
364
+ )
365
+ logger.info(f"Rebooting component: {part}")
366
+ except Exception as e:
367
+ raise RuntimeError(f"Failed to reboot component {part}: {e}") from e
368
+
369
+ def clear_error(
370
+ self,
371
+ part: Literal["left_arm", "right_arm", "chassis", "head"] | str,
372
+ ) -> None:
373
+ """Clear error state for a specific component.
374
+
375
+ Args:
376
+ part: Component to clear error state for.
377
+
378
+ Raises:
379
+ ValueError: If the specified component is invalid.
380
+ RuntimeError: If the error clearing operation fails.
381
+ """
382
+ component_map = {
383
+ "left_arm": dexcontrol_query_pb2.ClearError.Component.LEFT_ARM,
384
+ "right_arm": dexcontrol_query_pb2.ClearError.Component.RIGHT_ARM,
385
+ "chassis": dexcontrol_query_pb2.ClearError.Component.CHASSIS,
386
+ "head": dexcontrol_query_pb2.ClearError.Component.HEAD,
387
+ }
388
+
389
+ if part not in component_map:
390
+ raise ValueError(f"Invalid component: {part}")
391
+
392
+ try:
393
+ query_msg = dexcontrol_query_pb2.ClearError(component=component_map[part])
394
+ self._zenoh_session.get(
395
+ resolve_key_name(self._configs.clear_error_query_name),
396
+ handler=lambda reply: logger.info(f"Cleared error of {part}"),
397
+ payload=query_msg.SerializeToString(),
398
+ )
399
+ except Exception as e:
400
+ raise RuntimeError(
401
+ f"Failed to clear error for component {part}: {e}"
402
+ ) from e
403
+
404
+ def _show_version_info(self, version_info: dict[str, Any]) -> None:
405
+ """Display comprehensive version information in a formatted table.
406
+
407
+ Args:
408
+ version_info: Dictionary containing server and client version information.
409
+ """
410
+ from rich.console import Console
411
+ from rich.table import Table
412
+
413
+ console = Console()
414
+ table = Table(title="🤖 Robot System Version Information")
415
+
416
+ table.add_column("Component", justify="left", style="cyan", no_wrap=True)
417
+ table.add_column("Hardware Ver.", justify="center", style="magenta")
418
+ table.add_column("Software Ver.", justify="center", style="green")
419
+ table.add_column("Compile Time", justify="center", style="yellow")
420
+ table.add_column("Main Hash", justify="center", style="blue")
421
+ table.add_column("Sub Hash", justify="center", style="red")
422
+
423
+ # Display server components
424
+ server_info = version_info.get("server", {})
425
+ for component, info in server_info.items():
426
+ if isinstance(info, dict):
427
+ table.add_row(
428
+ component,
429
+ str(info.get("hardware_version", "N/A")),
430
+ str(info.get("software_version", "N/A")),
431
+ str(info.get("compile_time", "N/A")),
432
+ str(info.get("main_hash", "N/A")[:8])
433
+ if info.get("main_hash")
434
+ else "N/A",
435
+ str(info.get("sub_hash", "N/A")[:8])
436
+ if info.get("sub_hash")
437
+ else "N/A",
438
+ )
439
+
440
+ console.print(table)
dexcontrol/core/torso.py CHANGED
@@ -49,13 +49,18 @@ class Torso(RobotJointComponent):
49
49
  super().__init__(
50
50
  state_sub_topic=configs.state_sub_topic,
51
51
  control_pub_topic=configs.control_pub_topic,
52
- state_message_type=dexcontrol_msg_pb2.TorsoState,
52
+ state_message_type=dexcontrol_msg_pb2.MotorStateWithCurrent,
53
53
  zenoh_session=zenoh_session,
54
54
  joint_name=configs.joint_name,
55
+ joint_limit=configs.joint_limit
56
+ if hasattr(configs, "joint_limit")
57
+ else None,
58
+ joint_vel_limit=configs.joint_vel_limit
59
+ if hasattr(configs, "joint_vel_limit")
60
+ else None,
55
61
  pose_pool=configs.pose_pool,
56
62
  )
57
- self.default_vel = configs.default_vel
58
- self.max_vel = configs.max_vel
63
+ assert self._joint_vel_limit is not None, "joint_vel_limit is not set"
59
64
 
60
65
  def set_joint_pos_vel(
61
66
  self,
@@ -104,10 +109,19 @@ class Torso(RobotJointComponent):
104
109
  joint_pos = self._convert_joint_cmd_to_array(joint_pos)
105
110
  joint_vel = self._process_joint_velocities(joint_vel, joint_pos)
106
111
 
112
+ if self._joint_limit is not None:
113
+ joint_pos = np.clip(
114
+ joint_pos, self._joint_limit[:, 0], self._joint_limit[:, 1]
115
+ )
116
+ if self._joint_vel_limit is not None:
117
+ joint_vel = np.clip(
118
+ joint_vel, -self._joint_vel_limit, self._joint_vel_limit
119
+ )
120
+
107
121
  # Create and send control message
108
- control_msg = dexcontrol_msg_pb2.TorsoCommand()
109
- control_msg.joint_pos.extend(joint_pos.tolist())
110
- control_msg.joint_vel.extend(joint_vel.tolist())
122
+ control_msg = dexcontrol_msg_pb2.MotorPosVelCommand()
123
+ control_msg.pos.extend(joint_pos.tolist())
124
+ control_msg.vel.extend(joint_vel.tolist())
111
125
  self._publish_control(control_msg)
112
126
 
113
127
  # Wait if specified
@@ -207,12 +221,16 @@ class Torso(RobotJointComponent):
207
221
  if motion_norm < 1e-6: # Avoid division by zero
208
222
  return np.zeros(3, dtype=np.float32)
209
223
 
210
- # Scale velocities by default velocity
211
- return (joint_motion / motion_norm) * self.default_vel
224
+ default_vel = (
225
+ 0.6 if self._joint_vel_limit is None else np.min(self._joint_vel_limit)
226
+ )
227
+ return (joint_motion / motion_norm) * default_vel
212
228
 
213
229
  if isinstance(joint_vel, (int, float)):
214
230
  # Single value - apply to all joints
215
231
  return np.full(3, joint_vel, dtype=np.float32)
216
232
 
217
- # Convert to array and clip to max velocity
218
- return self._convert_joint_cmd_to_array(joint_vel, clip_value=self.max_vel)
233
+ # Convert to array and clip to velocity limits
234
+ return self._convert_joint_cmd_to_array(
235
+ joint_vel, clip_value=self._joint_vel_limit
236
+ )
@@ -25,47 +25,37 @@ _sym_db = _symbol_database.Default()
25
25
 
26
26
 
27
27
 
28
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x64\x65xcontrol_msg.proto\x12\ndexcontrol\"V\n\x08\x41rmState\x12\x11\n\tjoint_pos\x18\x01 \x03(\x02\x12\x11\n\tjoint_vel\x18\x02 \x03(\x02\x12\x11\n\tjoint_cur\x18\x03 \x03(\x02\x12\x11\n\tjoint_err\x18\x04 \x03(\r\"F\n\tHandState\x12\x11\n\tjoint_pos\x18\x01 \x03(\x02\x12\x11\n\tjoint_vel\x18\x02 \x03(\x02\x12\x13\n\x0bjoint_statu\x18\x03 \x03(\r\"1\n\tHeadState\x12\x11\n\tjoint_pos\x18\x01 \x03(\x02\x12\x11\n\tjoint_vel\x18\x02 \x03(\x02\"2\n\nTorsoState\x12\x11\n\tjoint_pos\x18\x01 \x03(\x02\x12\x11\n\tjoint_vel\x18\x02 \x03(\x02\"a\n\x10SingleWheelState\x12\x14\n\x0csteering_pos\x18\x01 \x01(\x02\x12\x11\n\twheel_pos\x18\x02 \x01(\x02\x12\x11\n\twheel_vel\x18\x03 \x01(\x02\x12\x11\n\twheel_cur\x18\x04 \x01(\x02\"g\n\x0c\x43hassisState\x12*\n\x04left\x18\x01 \x01(\x0b\x32\x1c.dexcontrol.SingleWheelState\x12+\n\x05right\x18\x02 \x01(\x0b\x32\x1c.dexcontrol.SingleWheelState\"j\n\x08\x42MSState\x12\x0f\n\x07voltage\x18\x01 \x01(\x02\x12\x0f\n\x07\x63urrent\x18\x02 \x01(\x02\x12\x13\n\x0btemperature\x18\x03 \x01(\x02\x12\x12\n\npercentage\x18\x04 \x01(\r\x12\x13\n\x0bis_charging\x18\x05 \x01(\x08\"H\n\x0bWrenchState\x12\x0e\n\x06wrench\x18\x01 \x03(\x02\x12\x13\n\x0b\x62lue_button\x18\x02 \x01(\x08\x12\x14\n\x0cgreen_button\x18\x03 \x01(\x08\"D\n\nEStopState\x12\x16\n\x0e\x62utton_pressed\x18\x01 \x01(\x08\x12\x1e\n\x16software_estop_enabled\x18\x02 \x01(\x08\"a\n\x0fUltrasonicState\x12\x12\n\nfront_left\x18\x01 \x01(\x02\x12\x13\n\x0b\x66ront_right\x18\x02 \x01(\x02\x12\x11\n\tback_left\x18\x03 \x01(\x02\x12\x12\n\nback_right\x18\x04 \x01(\x02\"\xa7\x01\n\x08IMUState\x12\r\n\x05\x61\x63\x63_x\x18\x01 \x01(\x02\x12\r\n\x05\x61\x63\x63_y\x18\x02 \x01(\x02\x12\r\n\x05\x61\x63\x63_z\x18\x03 \x01(\x02\x12\x0e\n\x06gyro_x\x18\x04 \x01(\x02\x12\x0e\n\x06gyro_y\x18\x05 \x01(\x02\x12\x0e\n\x06gyro_z\x18\x06 \x01(\x02\x12\x0e\n\x06quat_w\x18\x07 \x01(\x02\x12\x0e\n\x06quat_x\x18\x08 \x01(\x02\x12\x0e\n\x06quat_y\x18\t \x01(\x02\x12\x0e\n\x06quat_z\x18\n \x01(\x02\"\xa3\x01\n\nArmCommand\x12\x38\n\x0c\x63ommand_type\x18\x01 \x01(\x0e\x32\".dexcontrol.ArmCommand.CommandType\x12\x11\n\tjoint_pos\x18\x02 \x03(\x02\x12\x11\n\tjoint_vel\x18\x03 \x03(\x02\"5\n\x0b\x43ommandType\x12\x0c\n\x08POSITION\x10\x00\x12\x18\n\x14VELOCITY_FEEDFORWARD\x10\x01\" \n\x0bHandCommand\x12\x11\n\tjoint_pos\x18\x01 \x03(\x02\"3\n\x0bHeadCommand\x12\x11\n\tjoint_pos\x18\x01 \x03(\x02\x12\x11\n\tjoint_vel\x18\x02 \x03(\x02\"4\n\x0cTorsoCommand\x12\x11\n\tjoint_pos\x18\x01 \x03(\x02\x12\x11\n\tjoint_vel\x18\x02 \x03(\x02\"=\n\x12SingleWheelCommand\x12\x14\n\x0csteering_pos\x18\x01 \x01(\x02\x12\x11\n\twheel_vel\x18\x02 \x01(\x02\"m\n\x0e\x43hassisCommand\x12,\n\x04left\x18\x01 \x01(\x0b\x32\x1e.dexcontrol.SingleWheelCommand\x12-\n\x05right\x18\x02 \x01(\x0b\x32\x1e.dexcontrol.SingleWheelCommandb\x06proto3')
28
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14\x64\x65xcontrol_msg.proto\x12\ndexcontrol\"e\n\x14MotorStateWithTorque\x12\x0b\n\x03pos\x18\x01 \x03(\x02\x12\x0b\n\x03vel\x18\x02 \x03(\x02\x12\x0e\n\x06torque\x18\x03 \x03(\x02\x12\r\n\x05\x65rror\x18\x04 \x03(\r\x12\x14\n\x0ctimestamp_ns\x18\x05 \x01(\x04\"c\n\x15MotorStateWithCurrent\x12\x0b\n\x03pos\x18\x01 \x03(\x02\x12\x0b\n\x03vel\x18\x02 \x03(\x02\x12\x0b\n\x03\x63ur\x18\x03 \x03(\x02\x12\r\n\x05\x65rror\x18\x04 \x03(\r\x12\x14\n\x0ctimestamp_ns\x18\x05 \x01(\x04\"4\n\x0fMotorPosCommand\x12\x0b\n\x03pos\x18\x01 \x03(\x02\x12\x14\n\x0ctimestamp_ns\x18\x02 \x01(\x04\"4\n\x0fMotorVelCommand\x12\x0b\n\x03vel\x18\x01 \x03(\x02\x12\x14\n\x0ctimestamp_ns\x18\x02 \x01(\x04\"D\n\x12MotorPosVelCommand\x12\x0b\n\x03pos\x18\x01 \x03(\x02\x12\x0b\n\x03vel\x18\x02 \x03(\x02\x12\x14\n\x0ctimestamp_ns\x18\x03 \x01(\x04\"X\n\x19MotorPosVelCurrentCommand\x12\x0b\n\x03pos\x18\x01 \x03(\x02\x12\x0b\n\x03vel\x18\x02 \x03(\x02\x12\x0b\n\x03\x63ur\x18\x03 \x03(\x02\x12\x14\n\x0ctimestamp_ns\x18\x04 \x01(\x04\"C\n\x1d\x45ndEffectorPassThroughCommand\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x12\x14\n\x0ctimestamp_ns\x18\x02 \x01(\x04\"\x8f\x01\n\x08\x42MSState\x12\x0f\n\x07voltage\x18\x01 \x01(\x02\x12\x0f\n\x07\x63urrent\x18\x02 \x01(\x02\x12\x13\n\x0btemperature\x18\x03 \x01(\x02\x12\x12\n\npercentage\x18\x04 \x01(\r\x12\x13\n\x0bis_charging\x18\x05 \x01(\x08\x12\r\n\x05\x65rror\x18\x06 \x01(\r\x12\x14\n\x0ctimestamp_ns\x18\x07 \x01(\x04\"^\n\x0bWrenchState\x12\x0e\n\x06wrench\x18\x01 \x03(\x02\x12\x13\n\x0b\x62lue_button\x18\x02 \x01(\x08\x12\x14\n\x0cgreen_button\x18\x03 \x01(\x08\x12\x14\n\x0ctimestamp_ns\x18\x04 \x01(\x04\"\xbc\x01\n\nEStopState\x12\x1e\n\x16software_estop_enabled\x18\x01 \x01(\x08\x12\x1b\n\x13left_button_pressed\x18\x02 \x01(\x08\x12\x1c\n\x14right_button_pressed\x18\x03 \x01(\x08\x12\x1c\n\x14waist_button_pressed\x18\x04 \x01(\x08\x12\x1f\n\x17wireless_button_pressed\x18\x05 \x01(\x08\x12\x14\n\x0ctimestamp_ns\x18\x06 \x01(\x04\"w\n\x0fUltrasonicState\x12\x12\n\nfront_left\x18\x01 \x01(\x02\x12\x13\n\x0b\x66ront_right\x18\x02 \x01(\x02\x12\x11\n\tback_left\x18\x03 \x01(\x02\x12\x12\n\nback_right\x18\x04 \x01(\x02\x12\x14\n\x0ctimestamp_ns\x18\x05 \x01(\x04\"\xbd\x01\n\x08IMUState\x12\r\n\x05\x61\x63\x63_x\x18\x01 \x01(\x02\x12\r\n\x05\x61\x63\x63_y\x18\x02 \x01(\x02\x12\r\n\x05\x61\x63\x63_z\x18\x03 \x01(\x02\x12\x0e\n\x06gyro_x\x18\x04 \x01(\x02\x12\x0e\n\x06gyro_y\x18\x05 \x01(\x02\x12\x0e\n\x06gyro_z\x18\x06 \x01(\x02\x12\x0e\n\x06quat_w\x18\x07 \x01(\x02\x12\x0e\n\x06quat_x\x18\x08 \x01(\x02\x12\x0e\n\x06quat_y\x18\t \x01(\x02\x12\x0e\n\x06quat_z\x18\n \x01(\x02\x12\x14\n\x0ctimestamp_ns\x18\x0b \x01(\x04\";\n\x14HandTouchSensorState\x12\r\n\x05\x66orce\x18\x01 \x03(\x02\x12\x14\n\x0ctimestamp_ns\x18\x02 \x01(\x04\x62\x06proto3')
29
29
 
30
30
  _globals = globals()
31
31
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
32
32
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'dexcontrol_msg_pb2', _globals)
33
33
  if not _descriptor._USE_C_DESCRIPTORS:
34
34
  DESCRIPTOR._loaded_options = None
35
- _globals['_ARMSTATE']._serialized_start=36
36
- _globals['_ARMSTATE']._serialized_end=122
37
- _globals['_HANDSTATE']._serialized_start=124
38
- _globals['_HANDSTATE']._serialized_end=194
39
- _globals['_HEADSTATE']._serialized_start=196
40
- _globals['_HEADSTATE']._serialized_end=245
41
- _globals['_TORSOSTATE']._serialized_start=247
42
- _globals['_TORSOSTATE']._serialized_end=297
43
- _globals['_SINGLEWHEELSTATE']._serialized_start=299
44
- _globals['_SINGLEWHEELSTATE']._serialized_end=396
45
- _globals['_CHASSISSTATE']._serialized_start=398
46
- _globals['_CHASSISSTATE']._serialized_end=501
47
- _globals['_BMSSTATE']._serialized_start=503
48
- _globals['_BMSSTATE']._serialized_end=609
49
- _globals['_WRENCHSTATE']._serialized_start=611
50
- _globals['_WRENCHSTATE']._serialized_end=683
51
- _globals['_ESTOPSTATE']._serialized_start=685
52
- _globals['_ESTOPSTATE']._serialized_end=753
53
- _globals['_ULTRASONICSTATE']._serialized_start=755
54
- _globals['_ULTRASONICSTATE']._serialized_end=852
55
- _globals['_IMUSTATE']._serialized_start=855
56
- _globals['_IMUSTATE']._serialized_end=1022
57
- _globals['_ARMCOMMAND']._serialized_start=1025
58
- _globals['_ARMCOMMAND']._serialized_end=1188
59
- _globals['_ARMCOMMAND_COMMANDTYPE']._serialized_start=1135
60
- _globals['_ARMCOMMAND_COMMANDTYPE']._serialized_end=1188
61
- _globals['_HANDCOMMAND']._serialized_start=1190
62
- _globals['_HANDCOMMAND']._serialized_end=1222
63
- _globals['_HEADCOMMAND']._serialized_start=1224
64
- _globals['_HEADCOMMAND']._serialized_end=1275
65
- _globals['_TORSOCOMMAND']._serialized_start=1277
66
- _globals['_TORSOCOMMAND']._serialized_end=1329
67
- _globals['_SINGLEWHEELCOMMAND']._serialized_start=1331
68
- _globals['_SINGLEWHEELCOMMAND']._serialized_end=1392
69
- _globals['_CHASSISCOMMAND']._serialized_start=1394
70
- _globals['_CHASSISCOMMAND']._serialized_end=1503
35
+ _globals['_MOTORSTATEWITHTORQUE']._serialized_start=36
36
+ _globals['_MOTORSTATEWITHTORQUE']._serialized_end=137
37
+ _globals['_MOTORSTATEWITHCURRENT']._serialized_start=139
38
+ _globals['_MOTORSTATEWITHCURRENT']._serialized_end=238
39
+ _globals['_MOTORPOSCOMMAND']._serialized_start=240
40
+ _globals['_MOTORPOSCOMMAND']._serialized_end=292
41
+ _globals['_MOTORVELCOMMAND']._serialized_start=294
42
+ _globals['_MOTORVELCOMMAND']._serialized_end=346
43
+ _globals['_MOTORPOSVELCOMMAND']._serialized_start=348
44
+ _globals['_MOTORPOSVELCOMMAND']._serialized_end=416
45
+ _globals['_MOTORPOSVELCURRENTCOMMAND']._serialized_start=418
46
+ _globals['_MOTORPOSVELCURRENTCOMMAND']._serialized_end=506
47
+ _globals['_ENDEFFECTORPASSTHROUGHCOMMAND']._serialized_start=508
48
+ _globals['_ENDEFFECTORPASSTHROUGHCOMMAND']._serialized_end=575
49
+ _globals['_BMSSTATE']._serialized_start=578
50
+ _globals['_BMSSTATE']._serialized_end=721
51
+ _globals['_WRENCHSTATE']._serialized_start=723
52
+ _globals['_WRENCHSTATE']._serialized_end=817
53
+ _globals['_ESTOPSTATE']._serialized_start=820
54
+ _globals['_ESTOPSTATE']._serialized_end=1008
55
+ _globals['_ULTRASONICSTATE']._serialized_start=1010
56
+ _globals['_ULTRASONICSTATE']._serialized_end=1129
57
+ _globals['_IMUSTATE']._serialized_start=1132
58
+ _globals['_IMUSTATE']._serialized_end=1321
59
+ _globals['_HANDTOUCHSENSORSTATE']._serialized_start=1323
60
+ _globals['_HANDTOUCHSENSORSTATE']._serialized_end=1382
71
61
  # @@protoc_insertion_point(module_scope)