Left/Right sides + other fixes
This commit is contained in:
@@ -25,11 +25,17 @@ from ..config import RobotConfig
|
|||||||
@dataclass
|
@dataclass
|
||||||
class HopeJrHandConfig(RobotConfig):
|
class HopeJrHandConfig(RobotConfig):
|
||||||
port: str # Port to connect to the hand
|
port: str # Port to connect to the hand
|
||||||
|
side: str # "left" / "right"
|
||||||
|
|
||||||
disable_torque_on_disconnect: bool = True
|
disable_torque_on_disconnect: bool = True
|
||||||
|
|
||||||
cameras: dict[str, CameraConfig] = field(default_factory=dict)
|
cameras: dict[str, CameraConfig] = field(default_factory=dict)
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
super().__post_init__()
|
||||||
|
if self.side not in ["right", "left"]:
|
||||||
|
raise ValueError(self.side)
|
||||||
|
|
||||||
|
|
||||||
@RobotConfig.register_subclass("hope_jr_arm")
|
@RobotConfig.register_subclass("hope_jr_arm")
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -32,6 +32,31 @@ from .config_hope_jr import HopeJrHandConfig
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
RIGHT_HAND_INVERSIONS = [
|
||||||
|
"thumb_mcp",
|
||||||
|
"thumb_dip",
|
||||||
|
"index_ulnar_flexor",
|
||||||
|
"middle_ulnar_flexor",
|
||||||
|
"ring_ulnar_flexor",
|
||||||
|
"ring_pip_dip",
|
||||||
|
"pinky_ulnar_flexor",
|
||||||
|
"pinky_pip_dip",
|
||||||
|
]
|
||||||
|
|
||||||
|
LEFT_HAND_INVERSIONS = [
|
||||||
|
"thumb_cmc",
|
||||||
|
"thumb_mcp",
|
||||||
|
"thumb_dip",
|
||||||
|
"index_radial_flexor",
|
||||||
|
"index_pip_dip",
|
||||||
|
"middle_radial_flexor",
|
||||||
|
"middle_pip_dip",
|
||||||
|
"ring_radial_flexor",
|
||||||
|
"ring_pip_dip",
|
||||||
|
"pinky_radial_flexor",
|
||||||
|
"pinky_pip_dip",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class HopeJrHand(Robot):
|
class HopeJrHand(Robot):
|
||||||
config_class = HopeJrHandConfig
|
config_class = HopeJrHandConfig
|
||||||
@@ -69,17 +94,7 @@ class HopeJrHand(Robot):
|
|||||||
protocol_version=1,
|
protocol_version=1,
|
||||||
)
|
)
|
||||||
self.cameras = make_cameras_from_configs(config.cameras)
|
self.cameras = make_cameras_from_configs(config.cameras)
|
||||||
|
self.inverted_motors = RIGHT_HAND_INVERSIONS if config.side == "right" else LEFT_HAND_INVERSIONS
|
||||||
self.inverted_motors = [
|
|
||||||
"thumb_mcp",
|
|
||||||
"thumb_dip",
|
|
||||||
"index_ulnar_flexor",
|
|
||||||
"middle_ulnar_flexor",
|
|
||||||
"ring_ulnar_flexor",
|
|
||||||
"ring_pip_dip",
|
|
||||||
"pinky_ulnar_flexor",
|
|
||||||
"pinky_pip_dip",
|
|
||||||
]
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _motors_ft(self) -> dict[str, type]:
|
def _motors_ft(self) -> dict[str, type]:
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
INDEX_SPLAY = 0.2
|
INDEX_SPLAY = 0.3
|
||||||
MIDDLE_SPLAY = 0.1
|
MIDDLE_SPLAY = 0.3
|
||||||
RING_SPLAY = 0.1
|
RING_SPLAY = 0.3
|
||||||
PINKY_SPLAY = -0.1
|
PINKY_SPLAY = 0.5
|
||||||
|
|
||||||
|
|
||||||
def get_ulnar_flexion(flexion: float, abduction: float, splay: float):
|
def get_ulnar_flexion(flexion: float, abduction: float, splay: float):
|
||||||
ulnar_component = max(-abduction, 0)
|
# ulnar_component = max(-abduction, 0)
|
||||||
|
ulnar_component = -abduction
|
||||||
return ulnar_component * splay + flexion * (1 - splay)
|
return ulnar_component * splay + flexion * (1 - splay)
|
||||||
|
|
||||||
|
|
||||||
def get_radial_flexion(flexion: float, abduction: float, splay: float):
|
def get_radial_flexion(flexion: float, abduction: float, splay: float):
|
||||||
radial_component = max(abduction, 0)
|
radial_component = abduction
|
||||||
|
# radial_component = max(abduction, 0)
|
||||||
return radial_component * splay + flexion * (1 - splay)
|
return radial_component * splay + flexion * (1 - splay)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,13 @@ from ..config import TeleoperatorConfig
|
|||||||
@dataclass
|
@dataclass
|
||||||
class HomonculusGloveConfig(TeleoperatorConfig):
|
class HomonculusGloveConfig(TeleoperatorConfig):
|
||||||
port: str # Port to connect to the glove
|
port: str # Port to connect to the glove
|
||||||
|
side: str # "left" / "right"
|
||||||
baud_rate: int = 115_200
|
baud_rate: int = 115_200
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.side not in ["right", "left"]:
|
||||||
|
raise ValueError(self.side)
|
||||||
|
|
||||||
|
|
||||||
@TeleoperatorConfig.register_subclass("homonculus_arm")
|
@TeleoperatorConfig.register_subclass("homonculus_arm")
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ class HomonculusArm(Teleoperator):
|
|||||||
"wrist_pitch": int(raw_values[0]),
|
"wrist_pitch": int(raw_values[0]),
|
||||||
}
|
}
|
||||||
|
|
||||||
with self._lock:
|
with self.lock:
|
||||||
self._state = joint_angles
|
self._state = joint_angles
|
||||||
self.new_state_event.set()
|
self.new_state_event.set()
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,28 @@ from .config_homonculus import HomonculusGloveConfig
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
LEFT_HAND_INVERSIONS = [
|
||||||
|
"thumb_cmc",
|
||||||
|
"index_dip",
|
||||||
|
"middle_mcp_abduction",
|
||||||
|
"middle_dip",
|
||||||
|
"pinky_mcp_abduction",
|
||||||
|
"pinky_dip",
|
||||||
|
]
|
||||||
|
|
||||||
|
RIGHT_HAND_INVERSIONS = [
|
||||||
|
"thumb_mcp",
|
||||||
|
"thumb_cmc",
|
||||||
|
"index_mcp_abduction",
|
||||||
|
"index_dip",
|
||||||
|
"middle_mcp_abduction",
|
||||||
|
"middle_dip",
|
||||||
|
"ring_mcp_abduction",
|
||||||
|
"ring_mcp_flexion",
|
||||||
|
"ring_dip",
|
||||||
|
"pinky_mcp_abduction",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class HomonculusGlove(Teleoperator):
|
class HomonculusGlove(Teleoperator):
|
||||||
"""
|
"""
|
||||||
@@ -62,14 +84,7 @@ class HomonculusGlove(Teleoperator):
|
|||||||
"pinky_mcp_flexion": MotorNormMode.RANGE_0_100,
|
"pinky_mcp_flexion": MotorNormMode.RANGE_0_100,
|
||||||
"pinky_dip": MotorNormMode.RANGE_0_100,
|
"pinky_dip": MotorNormMode.RANGE_0_100,
|
||||||
}
|
}
|
||||||
self.inverted_joints = [
|
self.inverted_joints = RIGHT_HAND_INVERSIONS if config.side == "right" else LEFT_HAND_INVERSIONS
|
||||||
"thumb_cmc",
|
|
||||||
"index_dip",
|
|
||||||
"middle_mcp_abduction",
|
|
||||||
"middle_dip",
|
|
||||||
"pinky_mcp_abduction",
|
|
||||||
"pinky_dip",
|
|
||||||
]
|
|
||||||
|
|
||||||
self._state: dict[str, float] | None = None
|
self._state: dict[str, float] | None = None
|
||||||
self.new_state_event = threading.Event()
|
self.new_state_event = threading.Event()
|
||||||
@@ -158,6 +173,8 @@ class HomonculusGlove(Teleoperator):
|
|||||||
elif not isinstance(joints, list):
|
elif not isinstance(joints, list):
|
||||||
raise TypeError(joints)
|
raise TypeError(joints)
|
||||||
|
|
||||||
|
display_len = max(len(key) for key in joints)
|
||||||
|
|
||||||
start_positions = self._read(joints, normalize=False)
|
start_positions = self._read(joints, normalize=False)
|
||||||
mins = start_positions.copy()
|
mins = start_positions.copy()
|
||||||
maxes = start_positions.copy()
|
maxes = start_positions.copy()
|
||||||
@@ -168,9 +185,11 @@ class HomonculusGlove(Teleoperator):
|
|||||||
|
|
||||||
if display_values:
|
if display_values:
|
||||||
print("\n-------------------------------------------")
|
print("\n-------------------------------------------")
|
||||||
print(f"{'NAME':<15} | {'MIN':>6} | {'POS':>6} | {'MAX':>6}")
|
print(f"{'NAME':<{display_len}} | {'MIN':>6} | {'POS':>6} | {'MAX':>6}")
|
||||||
for joint in joints:
|
for joint in joints:
|
||||||
print(f"{joint:<15} | {mins[joint]:>6} | {positions[joint]:>6} | {maxes[joint]:>6}")
|
print(
|
||||||
|
f"{joint:<{display_len}} | {mins[joint]:>6} | {positions[joint]:>6} | {maxes[joint]:>6}"
|
||||||
|
)
|
||||||
|
|
||||||
if enter_pressed():
|
if enter_pressed():
|
||||||
break
|
break
|
||||||
|
|||||||
Reference in New Issue
Block a user