dexcontrol 0.2.4__py3-none-any.whl → 0.2.10__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.
- dexcontrol/config/core/arm.py +2 -0
- dexcontrol/config/core/hand.py +5 -16
- dexcontrol/config/sensors/cameras/__init__.py +2 -0
- dexcontrol/config/sensors/cameras/rgb_camera.py +24 -7
- dexcontrol/config/sensors/cameras/zed_camera.py +34 -15
- dexcontrol/config/sensors/vega_sensors.py +1 -0
- dexcontrol/config/vega.py +6 -0
- dexcontrol/core/arm.py +33 -6
- dexcontrol/core/component.py +51 -2
- dexcontrol/core/hand.py +81 -13
- dexcontrol/core/head.py +20 -3
- dexcontrol/core/torso.py +20 -5
- dexcontrol/proto/dexcontrol_query_pb2.py +15 -15
- dexcontrol/proto/dexcontrol_query_pb2.pyi +6 -2
- dexcontrol/robot.py +112 -37
- dexcontrol/sensors/camera/rgb_camera.py +98 -29
- dexcontrol/sensors/camera/zed_camera.py +214 -189
- dexcontrol/sensors/lidar/rplidar.py +13 -30
- dexcontrol/utils/pb_utils.py +6 -1
- dexcontrol/utils/subscribers/camera.py +1 -1
- dexcontrol/utils/subscribers/lidar.py +16 -45
- dexcontrol/utils/subscribers/rtc.py +2 -1
- dexcontrol/utils/viz_utils.py +4 -4
- {dexcontrol-0.2.4.dist-info → dexcontrol-0.2.10.dist-info}/METADATA +42 -17
- {dexcontrol-0.2.4.dist-info → dexcontrol-0.2.10.dist-info}/RECORD +27 -27
- {dexcontrol-0.2.4.dist-info → dexcontrol-0.2.10.dist-info}/WHEEL +0 -0
- {dexcontrol-0.2.4.dist-info → dexcontrol-0.2.10.dist-info}/licenses/LICENSE +0 -0
dexcontrol/config/core/arm.py
CHANGED
|
@@ -21,6 +21,8 @@ class ArmConfig:
|
|
|
21
21
|
control_pub_topic: str = "control/arm/right"
|
|
22
22
|
set_mode_query: str = "mode/arm/right"
|
|
23
23
|
dof: int = 7
|
|
24
|
+
default_max_vel: float = 2.0 # do not go over 3.0
|
|
25
|
+
default_control_hz: int = 100
|
|
24
26
|
joint_name: list[str] = field(
|
|
25
27
|
default_factory=lambda: [f"R_arm_j{i + 1}" for i in range(7)]
|
|
26
28
|
)
|
dexcontrol/config/core/hand.py
CHANGED
|
@@ -28,20 +28,9 @@ class HandConfig:
|
|
|
28
28
|
]
|
|
29
29
|
)
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
default_factory=lambda: [0.1834, 0.2891, 0.2801, 0.284, 0.2811, -0.0158]
|
|
37
|
-
)
|
|
38
|
-
joint_pos_close: list[float] = field(
|
|
39
|
-
default_factory=lambda: [
|
|
40
|
-
-0.3468,
|
|
41
|
-
-1.0946,
|
|
42
|
-
-1.0844,
|
|
43
|
-
-1.0154,
|
|
44
|
-
-1.0118,
|
|
45
|
-
1.6,
|
|
46
|
-
]
|
|
31
|
+
pose_pool: dict[str, list[float]] = field(
|
|
32
|
+
default_factory=lambda: {
|
|
33
|
+
"open": [0.1834, 0.2891, 0.2801, 0.284, 0.2811, -0.0158],
|
|
34
|
+
"close": [-0.3468, -1.0946, -1.0844, -1.0154, -1.0118, 1.6],
|
|
35
|
+
}
|
|
47
36
|
)
|
|
@@ -13,16 +13,33 @@ from dataclasses import dataclass, field
|
|
|
13
13
|
|
|
14
14
|
@dataclass
|
|
15
15
|
class RGBCameraConfig:
|
|
16
|
+
"""Configuration for the RGBCameraSensor.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
_target_: The target class to instantiate.
|
|
20
|
+
name: A unique name for the sensor instance.
|
|
21
|
+
enable: Whether the sensor is enabled.
|
|
22
|
+
use_rtc: If True, uses the high-performance RTCSubscriber. If False,
|
|
23
|
+
uses the standard RGBCameraSubscriber with a Zenoh topic.
|
|
24
|
+
enable_fps_tracking: If True, tracks and logs the FPS of the stream.
|
|
25
|
+
fps_log_interval: The interval in seconds for logging FPS.
|
|
26
|
+
subscriber_config: A dictionary containing the configuration for the
|
|
27
|
+
underlying subscriber (either RTC or standard).
|
|
28
|
+
"""
|
|
29
|
+
|
|
16
30
|
_target_: str = "dexcontrol.sensors.camera.rgb_camera.RGBCameraSensor"
|
|
17
31
|
name: str = "rgb_camera"
|
|
32
|
+
enable: bool = False
|
|
33
|
+
use_rtc: bool = True
|
|
18
34
|
enable_fps_tracking: bool = False
|
|
19
35
|
fps_log_interval: int = 30
|
|
20
|
-
|
|
36
|
+
|
|
21
37
|
subscriber_config: dict = field(
|
|
22
|
-
default_factory=lambda:
|
|
23
|
-
rgb
|
|
24
|
-
enable
|
|
25
|
-
info_key
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
default_factory=lambda: {
|
|
39
|
+
"rgb": {
|
|
40
|
+
"enable": True,
|
|
41
|
+
"info_key": "camera/rgb/info",
|
|
42
|
+
"topic": "camera/rgb",
|
|
43
|
+
}
|
|
44
|
+
}
|
|
28
45
|
)
|
|
@@ -13,24 +13,43 @@ from dataclasses import dataclass, field
|
|
|
13
13
|
|
|
14
14
|
@dataclass
|
|
15
15
|
class ZedCameraConfig:
|
|
16
|
+
"""Configuration for the ZedCameraSensor.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
_target_: The target class to instantiate.
|
|
20
|
+
name: A unique name for the sensor instance.
|
|
21
|
+
enable: Whether the sensor is enabled.
|
|
22
|
+
use_rtc: If True, RGB streams use the high-performance RTCSubscriber.
|
|
23
|
+
If False, they use the standard RGBCameraSubscriber. Depth
|
|
24
|
+
always uses a standard Zenoh subscriber.
|
|
25
|
+
enable_fps_tracking: If True, tracks and logs the FPS of all streams.
|
|
26
|
+
fps_log_interval: The interval in seconds for logging FPS.
|
|
27
|
+
subscriber_config: A dictionary containing the configurations for each
|
|
28
|
+
individual stream (left_rgb, right_rgb, depth).
|
|
29
|
+
"""
|
|
30
|
+
|
|
16
31
|
_target_: str = "dexcontrol.sensors.camera.zed_camera.ZedCameraSensor"
|
|
17
32
|
name: str = "zed_camera"
|
|
33
|
+
enable: bool = False
|
|
34
|
+
use_rtc: bool = True
|
|
18
35
|
enable_fps_tracking: bool = False
|
|
19
36
|
fps_log_interval: int = 30
|
|
20
|
-
|
|
37
|
+
|
|
21
38
|
subscriber_config: dict = field(
|
|
22
|
-
default_factory=lambda:
|
|
23
|
-
left_rgb
|
|
24
|
-
enable
|
|
25
|
-
info_key
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
default_factory=lambda: {
|
|
40
|
+
"left_rgb": {
|
|
41
|
+
"enable": True,
|
|
42
|
+
"info_key": "camera/head/left_rgb/info",
|
|
43
|
+
"topic": "camera/head/left_rgb",
|
|
44
|
+
},
|
|
45
|
+
"right_rgb": {
|
|
46
|
+
"enable": True,
|
|
47
|
+
"info_key": "camera/head/right_rgb/info",
|
|
48
|
+
"topic": "camera/head/right_rgb",
|
|
49
|
+
},
|
|
50
|
+
"depth": {
|
|
51
|
+
"enable": True,
|
|
52
|
+
"topic": "camera/head/depth",
|
|
53
|
+
},
|
|
54
|
+
}
|
|
36
55
|
)
|
dexcontrol/config/vega.py
CHANGED
|
@@ -167,6 +167,12 @@ class Vega1Config(VegaConfig):
|
|
|
167
167
|
wheels_dist=0.45,
|
|
168
168
|
)
|
|
169
169
|
)
|
|
170
|
+
head: HeadConfig = field(
|
|
171
|
+
default_factory=lambda: HeadConfig(
|
|
172
|
+
joint_limit_lower=[-1.483, -2.792, -1.378],
|
|
173
|
+
joint_limit_upper=[1.483, 2.792, 1.483],
|
|
174
|
+
)
|
|
175
|
+
)
|
|
170
176
|
|
|
171
177
|
|
|
172
178
|
# Register variant configurations
|
dexcontrol/core/arm.py
CHANGED
|
@@ -15,7 +15,7 @@ communication and the ArmWrenchSensor class for reading wrench sensor data.
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
import time
|
|
18
|
-
from typing import Final, Literal
|
|
18
|
+
from typing import Any, Final, Literal
|
|
19
19
|
|
|
20
20
|
import numpy as np
|
|
21
21
|
import zenoh
|
|
@@ -72,6 +72,15 @@ class Arm(RobotJointComponent):
|
|
|
72
72
|
configs.wrench_sub_topic, zenoh_session
|
|
73
73
|
)
|
|
74
74
|
|
|
75
|
+
self._default_max_vel = configs.default_max_vel
|
|
76
|
+
self._default_control_hz = configs.default_control_hz
|
|
77
|
+
if self._default_max_vel > 3.0:
|
|
78
|
+
logger.warning(
|
|
79
|
+
f"Max velocity is set to {self._default_max_vel}, which is greater than 3.0. This is not recommended."
|
|
80
|
+
)
|
|
81
|
+
self._default_max_vel = 3.0
|
|
82
|
+
logger.warning("Max velocity is clamped to 3.0")
|
|
83
|
+
|
|
75
84
|
def set_mode(self, mode: Literal["position", "disable"]) -> None:
|
|
76
85
|
"""Sets the operating mode of the arm.
|
|
77
86
|
|
|
@@ -112,6 +121,8 @@ class Arm(RobotJointComponent):
|
|
|
112
121
|
relative: bool = False,
|
|
113
122
|
wait_time: float = 0.0,
|
|
114
123
|
wait_kwargs: dict[str, float] | None = None,
|
|
124
|
+
exit_on_reach: bool = False,
|
|
125
|
+
exit_on_reach_kwargs: dict[str, Any] | None = None,
|
|
115
126
|
) -> None:
|
|
116
127
|
"""Controls the arm in joint position mode.
|
|
117
128
|
|
|
@@ -130,7 +141,8 @@ class Arm(RobotJointComponent):
|
|
|
130
141
|
wait_time > 0). Supported keys:
|
|
131
142
|
- control_hz: Control frequency in Hz (default: 100).
|
|
132
143
|
- max_vel: Maximum velocity in rad/s (default: 0.5).
|
|
133
|
-
|
|
144
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
145
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
134
146
|
Raises:
|
|
135
147
|
ValueError: If joint_pos dictionary contains invalid joint names.
|
|
136
148
|
"""
|
|
@@ -142,7 +154,13 @@ class Arm(RobotJointComponent):
|
|
|
142
154
|
)
|
|
143
155
|
|
|
144
156
|
if wait_time > 0.0:
|
|
145
|
-
self._execute_trajectory_motion(
|
|
157
|
+
self._execute_trajectory_motion(
|
|
158
|
+
resolved_joint_pos,
|
|
159
|
+
wait_time,
|
|
160
|
+
wait_kwargs,
|
|
161
|
+
exit_on_reach,
|
|
162
|
+
exit_on_reach_kwargs,
|
|
163
|
+
)
|
|
146
164
|
else:
|
|
147
165
|
# Convert to array format
|
|
148
166
|
if isinstance(resolved_joint_pos, (list, dict)):
|
|
@@ -156,6 +174,8 @@ class Arm(RobotJointComponent):
|
|
|
156
174
|
joint_pos: Float[np.ndarray, " N"] | list[float] | dict[str, float],
|
|
157
175
|
wait_time: float,
|
|
158
176
|
wait_kwargs: dict[str, float],
|
|
177
|
+
exit_on_reach: bool = False,
|
|
178
|
+
exit_on_reach_kwargs: dict[str, Any] | None = None,
|
|
159
179
|
) -> None:
|
|
160
180
|
"""Execute trajectory-based motion to target position.
|
|
161
181
|
|
|
@@ -163,10 +183,14 @@ class Arm(RobotJointComponent):
|
|
|
163
183
|
joint_pos: Target joint positions as list, numpy array, or dictionary.
|
|
164
184
|
wait_time: Total time for the motion.
|
|
165
185
|
wait_kwargs: Parameters for trajectory generation.
|
|
186
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
187
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
166
188
|
"""
|
|
167
189
|
# Set default parameters
|
|
168
|
-
control_hz = wait_kwargs.get("control_hz",
|
|
169
|
-
max_vel = wait_kwargs.get("max_vel",
|
|
190
|
+
control_hz = wait_kwargs.get("control_hz", self._default_control_hz)
|
|
191
|
+
max_vel = wait_kwargs.get("max_vel", self._default_max_vel)
|
|
192
|
+
exit_on_reach_kwargs = exit_on_reach_kwargs or {}
|
|
193
|
+
exit_on_reach_kwargs.setdefault("tolerance", 0.05)
|
|
170
194
|
|
|
171
195
|
# Create rate limiter and get current position
|
|
172
196
|
rate_limiter = RateLimiter(control_hz)
|
|
@@ -186,7 +210,6 @@ class Arm(RobotJointComponent):
|
|
|
186
210
|
trajectory, _ = generate_linear_trajectory(
|
|
187
211
|
current_joint_pos, target_pos, max_vel, control_hz
|
|
188
212
|
)
|
|
189
|
-
|
|
190
213
|
# Execute trajectory with time limit
|
|
191
214
|
start_time = time.time()
|
|
192
215
|
for pos in trajectory:
|
|
@@ -199,6 +222,10 @@ class Arm(RobotJointComponent):
|
|
|
199
222
|
while time.time() - start_time < wait_time:
|
|
200
223
|
self._send_position_command(target_pos)
|
|
201
224
|
rate_limiter.sleep()
|
|
225
|
+
if exit_on_reach and self.is_joint_pos_reached(
|
|
226
|
+
target_pos, **exit_on_reach_kwargs
|
|
227
|
+
):
|
|
228
|
+
break
|
|
202
229
|
|
|
203
230
|
def set_joint_pos_vel(
|
|
204
231
|
self,
|
dexcontrol/core/component.py
CHANGED
|
@@ -634,6 +634,8 @@ class RobotJointComponent(RobotComponent):
|
|
|
634
634
|
relative: bool = False,
|
|
635
635
|
wait_time: float = 0.0,
|
|
636
636
|
wait_kwargs: dict[str, float] | None = None,
|
|
637
|
+
exit_on_reach: bool = False,
|
|
638
|
+
exit_on_reach_kwargs: dict[str, Any] | None = None,
|
|
637
639
|
) -> None:
|
|
638
640
|
"""Send joint position control commands.
|
|
639
641
|
|
|
@@ -645,6 +647,8 @@ class RobotJointComponent(RobotComponent):
|
|
|
645
647
|
relative: If True, the joint positions are relative to the current position.
|
|
646
648
|
wait_time: Time to wait after sending command in seconds.
|
|
647
649
|
wait_kwargs: Optional parameters for trajectory generation.
|
|
650
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
651
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
648
652
|
|
|
649
653
|
Raises:
|
|
650
654
|
ValueError: If joint_pos dictionary contains invalid joint names.
|
|
@@ -659,6 +663,41 @@ class RobotJointComponent(RobotComponent):
|
|
|
659
663
|
self._send_position_command(joint_pos)
|
|
660
664
|
|
|
661
665
|
if wait_time > 0.0:
|
|
666
|
+
self._wait_for_position(
|
|
667
|
+
joint_pos, wait_time, exit_on_reach, exit_on_reach_kwargs
|
|
668
|
+
)
|
|
669
|
+
|
|
670
|
+
def _wait_for_position(
|
|
671
|
+
self,
|
|
672
|
+
joint_pos: Float[np.ndarray, " N"] | list[float] | dict[str, float],
|
|
673
|
+
wait_time: float,
|
|
674
|
+
exit_on_reach: bool = False,
|
|
675
|
+
exit_on_reach_kwargs: dict[str, Any] | None = None,
|
|
676
|
+
) -> None:
|
|
677
|
+
"""Wait for a specified time with optional early exit when position is reached.
|
|
678
|
+
|
|
679
|
+
Args:
|
|
680
|
+
joint_pos: Target joint positions to check against.
|
|
681
|
+
wait_time: Maximum time to wait in seconds.
|
|
682
|
+
exit_on_reach: If True, exit early when joint positions are reached.
|
|
683
|
+
exit_on_reach_kwargs: Optional parameters for position checking.
|
|
684
|
+
"""
|
|
685
|
+
if exit_on_reach:
|
|
686
|
+
# Set default tolerance if not provided
|
|
687
|
+
exit_on_reach_kwargs = exit_on_reach_kwargs or {}
|
|
688
|
+
exit_on_reach_kwargs.setdefault("tolerance", 0.05)
|
|
689
|
+
|
|
690
|
+
# Convert to expected format for is_joint_pos_reached
|
|
691
|
+
if isinstance(joint_pos, list):
|
|
692
|
+
joint_pos = np.array(joint_pos, dtype=np.float32)
|
|
693
|
+
|
|
694
|
+
# Wait until position is reached or timeout
|
|
695
|
+
start_time = time.time()
|
|
696
|
+
while time.time() - start_time < wait_time:
|
|
697
|
+
if self.is_joint_pos_reached(joint_pos, **exit_on_reach_kwargs):
|
|
698
|
+
break
|
|
699
|
+
time.sleep(0.01)
|
|
700
|
+
else:
|
|
662
701
|
time.sleep(wait_time)
|
|
663
702
|
|
|
664
703
|
def _send_position_command(self, joint_pos: Float[np.ndarray, " N"]) -> None:
|
|
@@ -679,12 +718,16 @@ class RobotJointComponent(RobotComponent):
|
|
|
679
718
|
self,
|
|
680
719
|
pose_name: str,
|
|
681
720
|
wait_time: float = 3.0,
|
|
721
|
+
exit_on_reach: bool = False,
|
|
722
|
+
exit_on_reach_kwargs: dict[str, float] | None = None,
|
|
682
723
|
) -> None:
|
|
683
724
|
"""Move the component to a predefined pose.
|
|
684
725
|
|
|
685
726
|
Args:
|
|
686
727
|
pose_name: Name of the pose to move to.
|
|
687
728
|
wait_time: Time to wait for the component to reach the pose.
|
|
729
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
730
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
688
731
|
|
|
689
732
|
Raises:
|
|
690
733
|
ValueError: If pose pool is not available or if an invalid pose name is provided.
|
|
@@ -696,7 +739,12 @@ class RobotJointComponent(RobotComponent):
|
|
|
696
739
|
f"Invalid pose name: {pose_name}. Available poses: {list(self._pose_pool.keys())}"
|
|
697
740
|
)
|
|
698
741
|
pose = self._pose_pool[pose_name]
|
|
699
|
-
self.set_joint_pos(
|
|
742
|
+
self.set_joint_pos(
|
|
743
|
+
pose,
|
|
744
|
+
wait_time=wait_time,
|
|
745
|
+
exit_on_reach=exit_on_reach,
|
|
746
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
747
|
+
)
|
|
700
748
|
|
|
701
749
|
def is_joint_pos_reached(
|
|
702
750
|
self,
|
|
@@ -819,11 +867,12 @@ class RobotJointComponent(RobotComponent):
|
|
|
819
867
|
else:
|
|
820
868
|
# Check all joints, ensuring arrays are same length
|
|
821
869
|
min_len = min(len(current_pos), len(target_pos))
|
|
822
|
-
|
|
870
|
+
is_reached = bool(
|
|
823
871
|
np.all(
|
|
824
872
|
np.abs(current_pos[:min_len] - target_pos[:min_len]) <= tolerance
|
|
825
873
|
)
|
|
826
874
|
)
|
|
875
|
+
return is_reached
|
|
827
876
|
|
|
828
877
|
def is_pose_reached(
|
|
829
878
|
self,
|
dexcontrol/core/hand.py
CHANGED
|
@@ -14,6 +14,8 @@ This module provides the Hand class for controlling a robotic hand through Zenoh
|
|
|
14
14
|
communication. It handles joint position control and state monitoring.
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
17
19
|
import numpy as np
|
|
18
20
|
import zenoh
|
|
19
21
|
from jaxtyping import Float
|
|
@@ -51,8 +53,8 @@ class Hand(RobotJointComponent):
|
|
|
51
53
|
)
|
|
52
54
|
|
|
53
55
|
# Store predefined hand positions as private attributes
|
|
54
|
-
self._joint_pos_open = np.array(configs.
|
|
55
|
-
self._joint_pos_close = np.array(configs.
|
|
56
|
+
self._joint_pos_open = np.array(configs.pose_pool["open"], dtype=np.float32)
|
|
57
|
+
self._joint_pos_close = np.array(configs.pose_pool["close"], dtype=np.float32)
|
|
56
58
|
|
|
57
59
|
def _send_position_command(
|
|
58
60
|
self, joint_pos: Float[np.ndarray, " N"] | list[float]
|
|
@@ -73,6 +75,8 @@ class Hand(RobotJointComponent):
|
|
|
73
75
|
relative: bool = False,
|
|
74
76
|
wait_time: float = 0.0,
|
|
75
77
|
wait_kwargs: dict[str, float] | None = None,
|
|
78
|
+
exit_on_reach: bool = False,
|
|
79
|
+
exit_on_reach_kwargs: dict[str, Any] | None = None,
|
|
76
80
|
) -> None:
|
|
77
81
|
"""Send joint position control commands to the hand.
|
|
78
82
|
|
|
@@ -84,27 +88,61 @@ class Hand(RobotJointComponent):
|
|
|
84
88
|
relative: If True, the joint positions are relative to the current position.
|
|
85
89
|
wait_time: Time to wait after setting the joint positions.
|
|
86
90
|
wait_kwargs: Optional parameters for trajectory generation (not used in Hand).
|
|
91
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
92
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
87
93
|
|
|
88
94
|
Raises:
|
|
89
95
|
ValueError: If joint_pos dictionary contains invalid joint names.
|
|
90
96
|
"""
|
|
91
|
-
super().set_joint_pos(
|
|
97
|
+
super().set_joint_pos(
|
|
98
|
+
joint_pos,
|
|
99
|
+
relative,
|
|
100
|
+
wait_time,
|
|
101
|
+
wait_kwargs,
|
|
102
|
+
exit_on_reach,
|
|
103
|
+
exit_on_reach_kwargs,
|
|
104
|
+
)
|
|
92
105
|
|
|
93
|
-
def open_hand(
|
|
106
|
+
def open_hand(
|
|
107
|
+
self,
|
|
108
|
+
wait_time: float = 0.0,
|
|
109
|
+
exit_on_reach: bool = False,
|
|
110
|
+
exit_on_reach_kwargs: dict[str, Any] | None = None,
|
|
111
|
+
) -> None:
|
|
94
112
|
"""Open the hand to the predefined open position.
|
|
95
113
|
|
|
96
114
|
Args:
|
|
97
115
|
wait_time: Time to wait after opening the hand.
|
|
116
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
117
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
98
118
|
"""
|
|
99
|
-
self.set_joint_pos(
|
|
119
|
+
self.set_joint_pos(
|
|
120
|
+
self._joint_pos_open,
|
|
121
|
+
wait_time=wait_time,
|
|
122
|
+
exit_on_reach=exit_on_reach,
|
|
123
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
124
|
+
)
|
|
100
125
|
|
|
101
|
-
def close_hand(
|
|
126
|
+
def close_hand(
|
|
127
|
+
self,
|
|
128
|
+
wait_time: float = 0.0,
|
|
129
|
+
exit_on_reach: bool = False,
|
|
130
|
+
exit_on_reach_kwargs: dict[str, Any] | None = None,
|
|
131
|
+
) -> None:
|
|
102
132
|
"""Close the hand to the predefined closed position.
|
|
103
133
|
|
|
104
134
|
Args:
|
|
105
135
|
wait_time: Time to wait after closing the hand.
|
|
136
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
137
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
138
|
+
|
|
106
139
|
"""
|
|
107
|
-
self.set_joint_pos(
|
|
140
|
+
self.set_joint_pos(
|
|
141
|
+
self._joint_pos_close,
|
|
142
|
+
wait_time=wait_time,
|
|
143
|
+
exit_on_reach=exit_on_reach,
|
|
144
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
145
|
+
)
|
|
108
146
|
|
|
109
147
|
|
|
110
148
|
class HandF5D6(Hand):
|
|
@@ -114,7 +152,12 @@ class HandF5D6(Hand):
|
|
|
114
152
|
the F5D6 hand model.
|
|
115
153
|
"""
|
|
116
154
|
|
|
117
|
-
def close_hand(
|
|
155
|
+
def close_hand(
|
|
156
|
+
self,
|
|
157
|
+
wait_time: float = 0.0,
|
|
158
|
+
exit_on_reach: bool = False,
|
|
159
|
+
exit_on_reach_kwargs: dict[str, Any] | None = None,
|
|
160
|
+
) -> None:
|
|
118
161
|
"""Close the hand fully using a two-step approach for better control."""
|
|
119
162
|
if self.is_joint_pos_reached(self._joint_pos_close, tolerance=0.1):
|
|
120
163
|
return
|
|
@@ -122,13 +165,28 @@ class HandF5D6(Hand):
|
|
|
122
165
|
# First step: Move to intermediate position
|
|
123
166
|
intermediate_pos = self._get_intermediate_close_position()
|
|
124
167
|
first_step_wait_time = 0.8
|
|
125
|
-
self.set_joint_pos(
|
|
168
|
+
self.set_joint_pos(
|
|
169
|
+
intermediate_pos,
|
|
170
|
+
wait_time=first_step_wait_time,
|
|
171
|
+
exit_on_reach=exit_on_reach,
|
|
172
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
173
|
+
)
|
|
126
174
|
|
|
127
175
|
# Second step: Move to final closed position
|
|
128
176
|
remaining_wait_time = max(0.0, wait_time - first_step_wait_time)
|
|
129
|
-
self.set_joint_pos(
|
|
177
|
+
self.set_joint_pos(
|
|
178
|
+
self._joint_pos_close,
|
|
179
|
+
wait_time=remaining_wait_time,
|
|
180
|
+
exit_on_reach=exit_on_reach,
|
|
181
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
182
|
+
)
|
|
130
183
|
|
|
131
|
-
def open_hand(
|
|
184
|
+
def open_hand(
|
|
185
|
+
self,
|
|
186
|
+
wait_time: float = 0.0,
|
|
187
|
+
exit_on_reach: bool = False,
|
|
188
|
+
exit_on_reach_kwargs: dict[str, Any] | None = None,
|
|
189
|
+
) -> None:
|
|
132
190
|
"""Open the hand fully using a two-step approach for better control."""
|
|
133
191
|
if self.is_joint_pos_reached(self._joint_pos_open, tolerance=0.1):
|
|
134
192
|
return
|
|
@@ -136,11 +194,21 @@ class HandF5D6(Hand):
|
|
|
136
194
|
# First step: Move to intermediate position
|
|
137
195
|
intermediate_pos = self._get_intermediate_open_position()
|
|
138
196
|
first_step_wait_time = 0.3
|
|
139
|
-
self.set_joint_pos(
|
|
197
|
+
self.set_joint_pos(
|
|
198
|
+
intermediate_pos,
|
|
199
|
+
wait_time=first_step_wait_time,
|
|
200
|
+
exit_on_reach=exit_on_reach,
|
|
201
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
202
|
+
)
|
|
140
203
|
|
|
141
204
|
# Second step: Move to final open position
|
|
142
205
|
remaining_wait_time = max(0.0, wait_time - first_step_wait_time)
|
|
143
|
-
self.set_joint_pos(
|
|
206
|
+
self.set_joint_pos(
|
|
207
|
+
self._joint_pos_open,
|
|
208
|
+
wait_time=remaining_wait_time,
|
|
209
|
+
exit_on_reach=exit_on_reach,
|
|
210
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
211
|
+
)
|
|
144
212
|
|
|
145
213
|
def _get_intermediate_close_position(self) -> np.ndarray:
|
|
146
214
|
"""Get intermediate position for closing hand.
|
dexcontrol/core/head.py
CHANGED
|
@@ -79,6 +79,8 @@ class Head(RobotJointComponent):
|
|
|
79
79
|
relative: bool = False,
|
|
80
80
|
wait_time: float = 0.0,
|
|
81
81
|
wait_kwargs: dict[str, float] | None = None,
|
|
82
|
+
exit_on_reach: bool = False,
|
|
83
|
+
exit_on_reach_kwargs: dict[str, float] | None = None,
|
|
82
84
|
) -> None:
|
|
83
85
|
"""Send joint position control commands to the head.
|
|
84
86
|
|
|
@@ -91,12 +93,19 @@ class Head(RobotJointComponent):
|
|
|
91
93
|
wait_time: Time to wait after sending command in seconds. If 0, returns
|
|
92
94
|
immediately after sending command.
|
|
93
95
|
wait_kwargs: Optional parameters for trajectory generation (not used in Head).
|
|
96
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
97
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
94
98
|
|
|
95
99
|
Raises:
|
|
96
100
|
ValueError: If joint_pos dictionary contains invalid joint names.
|
|
97
101
|
"""
|
|
98
102
|
self.set_joint_pos_vel(
|
|
99
|
-
joint_pos,
|
|
103
|
+
joint_pos,
|
|
104
|
+
joint_vel=None,
|
|
105
|
+
relative=relative,
|
|
106
|
+
wait_time=wait_time,
|
|
107
|
+
exit_on_reach=exit_on_reach,
|
|
108
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
100
109
|
)
|
|
101
110
|
|
|
102
111
|
def set_joint_pos_vel(
|
|
@@ -109,6 +118,8 @@ class Head(RobotJointComponent):
|
|
|
109
118
|
| None = None,
|
|
110
119
|
relative: bool = False,
|
|
111
120
|
wait_time: float = 0.0,
|
|
121
|
+
exit_on_reach: bool = False,
|
|
122
|
+
exit_on_reach_kwargs: dict[str, float] | None = None,
|
|
112
123
|
) -> None:
|
|
113
124
|
"""Send control commands to the head.
|
|
114
125
|
|
|
@@ -126,6 +137,8 @@ class Head(RobotJointComponent):
|
|
|
126
137
|
relative: If True, the joint positions are relative to the current position.
|
|
127
138
|
wait_time: Time to wait after sending command in seconds. If 0, returns
|
|
128
139
|
immediately after sending command.
|
|
140
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
141
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
129
142
|
|
|
130
143
|
Raises:
|
|
131
144
|
ValueError: If wait_time is negative or joint_pos dictionary contains
|
|
@@ -149,8 +162,12 @@ class Head(RobotJointComponent):
|
|
|
149
162
|
self._publish_control(control_msg)
|
|
150
163
|
|
|
151
164
|
# Wait if specified
|
|
152
|
-
|
|
153
|
-
|
|
165
|
+
self._wait_for_position(
|
|
166
|
+
joint_pos=joint_pos,
|
|
167
|
+
wait_time=wait_time,
|
|
168
|
+
exit_on_reach=exit_on_reach,
|
|
169
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
170
|
+
)
|
|
154
171
|
|
|
155
172
|
def set_mode(self, mode: Literal["enable", "disable"]) -> None:
|
|
156
173
|
"""Set the operating mode of the head.
|
dexcontrol/core/torso.py
CHANGED
|
@@ -14,8 +14,6 @@ This module provides the Torso class for controlling a robot torso through Zenoh
|
|
|
14
14
|
communication. It handles joint position and velocity control and state monitoring.
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
-
import time
|
|
18
|
-
|
|
19
17
|
import numpy as np
|
|
20
18
|
import zenoh
|
|
21
19
|
from jaxtyping import Float
|
|
@@ -69,6 +67,8 @@ class Torso(RobotJointComponent):
|
|
|
69
67
|
| None = None,
|
|
70
68
|
relative: bool = False,
|
|
71
69
|
wait_time: float = 0.0,
|
|
70
|
+
exit_on_reach: bool = False,
|
|
71
|
+
exit_on_reach_kwargs: dict[str, float] | None = None,
|
|
72
72
|
) -> None:
|
|
73
73
|
"""Send control commands to the torso.
|
|
74
74
|
|
|
@@ -86,6 +86,8 @@ class Torso(RobotJointComponent):
|
|
|
86
86
|
relative: If True, the joint positions are relative to the current position.
|
|
87
87
|
wait_time: Time to wait after sending command in seconds. If 0, returns
|
|
88
88
|
immediately after sending command.
|
|
89
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
90
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
89
91
|
|
|
90
92
|
Raises:
|
|
91
93
|
ValueError: If wait_time is negative or joint_pos dictionary contains
|
|
@@ -109,8 +111,12 @@ class Torso(RobotJointComponent):
|
|
|
109
111
|
self._publish_control(control_msg)
|
|
110
112
|
|
|
111
113
|
# Wait if specified
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
self._wait_for_position(
|
|
115
|
+
joint_pos=joint_pos,
|
|
116
|
+
wait_time=wait_time,
|
|
117
|
+
exit_on_reach=exit_on_reach,
|
|
118
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
119
|
+
)
|
|
114
120
|
|
|
115
121
|
def set_joint_pos(
|
|
116
122
|
self,
|
|
@@ -118,6 +124,8 @@ class Torso(RobotJointComponent):
|
|
|
118
124
|
relative: bool = False,
|
|
119
125
|
wait_time: float = 0.0,
|
|
120
126
|
wait_kwargs: dict[str, float] | None = None,
|
|
127
|
+
exit_on_reach: bool = False,
|
|
128
|
+
exit_on_reach_kwargs: dict[str, float] | None = None,
|
|
121
129
|
) -> None:
|
|
122
130
|
"""Send joint position control commands to the torso.
|
|
123
131
|
|
|
@@ -130,12 +138,19 @@ class Torso(RobotJointComponent):
|
|
|
130
138
|
wait_time: Time to wait after sending command in seconds. If 0, returns
|
|
131
139
|
immediately after sending command.
|
|
132
140
|
wait_kwargs: Optional parameters for trajectory generation (not used in Torso).
|
|
141
|
+
exit_on_reach: If True, the function will exit when the joint positions are reached.
|
|
142
|
+
exit_on_reach_kwargs: Optional parameters for exit when the joint positions are reached.
|
|
133
143
|
|
|
134
144
|
Raises:
|
|
135
145
|
ValueError: If joint_pos dictionary contains invalid joint names.
|
|
136
146
|
"""
|
|
137
147
|
self.set_joint_pos_vel(
|
|
138
|
-
joint_pos,
|
|
148
|
+
joint_pos,
|
|
149
|
+
joint_vel=None,
|
|
150
|
+
relative=relative,
|
|
151
|
+
wait_time=wait_time,
|
|
152
|
+
exit_on_reach=exit_on_reach,
|
|
153
|
+
exit_on_reach_kwargs=exit_on_reach_kwargs,
|
|
139
154
|
)
|
|
140
155
|
|
|
141
156
|
def stop(self) -> None:
|