From 2d7c2bc35ff444d57256eecf84b9c9e45c18ab4e Mon Sep 17 00:00:00 2001 From: gospar Date: Tue, 14 Oct 2025 15:22:59 +0200 Subject: [PATCH 01/15] robust invese kinematics --- .../kinematics/analytical_kinematics.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/reachy_mini/kinematics/analytical_kinematics.py b/src/reachy_mini/kinematics/analytical_kinematics.py index 0691b7d8..2422f2cd 100644 --- a/src/reachy_mini/kinematics/analytical_kinematics.py +++ b/src/reachy_mini/kinematics/analytical_kinematics.py @@ -67,10 +67,17 @@ def ik( """ _pose = pose.copy() _pose[:3, 3][2] += self.head_z_offset - - stewart_joints = self.kin.inverse_kinematics(_pose, body_yaw) # type: ignore[arg-type] - - return np.array([body_yaw] + stewart_joints) + + # inverse kinematics solution that modulates the body yaw to + # stay within the mechanical limits (max_body_yaw) + # additionally it makes sure the the relative yaw between the body and the head + # stays within the mechanical limits (max_relative_yaw) + reachy_joints = self.kin.inverse_kinematics_safe(_pose, + body_yaw = body_yaw, + max_relative_yaw = np.deg2rad(65), + max_body_yaw = np.deg2rad(160)) # type: ignore[arg-type] + + return np.array(reachy_joints) # type: ignore[arg-type] def fk( self, From f8229803f7a7aca7237ff965ead0152331453b45 Mon Sep 17 00:00:00 2001 From: gospar Date: Thu, 16 Oct 2025 09:08:52 +0200 Subject: [PATCH 02/15] remove elapsed time dumping --- src/reachy_mini/kinematics/analytical_kinematics.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/reachy_mini/kinematics/analytical_kinematics.py b/src/reachy_mini/kinematics/analytical_kinematics.py index 2422f2cd..62cd5cb3 100644 --- a/src/reachy_mini/kinematics/analytical_kinematics.py +++ b/src/reachy_mini/kinematics/analytical_kinematics.py @@ -65,6 +65,8 @@ def ik( check_collision and no_iterations are not used by AnalyticalKinematics. We keep them for compatibility with the other kinematics engines """ + # import time + # k = time.time() _pose = pose.copy() _pose[:3, 3][2] += self.head_z_offset @@ -76,7 +78,7 @@ def ik( body_yaw = body_yaw, max_relative_yaw = np.deg2rad(65), max_body_yaw = np.deg2rad(160)) # type: ignore[arg-type] - + # print("IK time {0:.3f}us".format((time.time() - k)*1e6)) return np.array(reachy_joints) # type: ignore[arg-type] def fk( From 47a108616fd807528834e10f65edd8802e9c8b2f Mon Sep 17 00:00:00 2001 From: gospar Date: Wed, 22 Oct 2025 10:15:10 +0200 Subject: [PATCH 03/15] bump the version of the rust_kinematics --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a66a0efa..48853f59 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,7 +24,7 @@ dependencies = [ "huggingface-hub==0.34.4", "sounddevice==0.5.1", "soundfile==0.13.1", - "reachy-mini-rust-kinematics>=1.0.1", + "reachy-mini-rust-kinematics>=1.0.2", "asgiref", "aiohttp", ] From 3f7209829ce6bd0cc1131853f2eadfbe725eb8fb Mon Sep 17 00:00:00 2001 From: gospar Date: Wed, 22 Oct 2025 10:45:22 +0200 Subject: [PATCH 04/15] ci launch --- src/reachy_mini/kinematics/analytical_kinematics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reachy_mini/kinematics/analytical_kinematics.py b/src/reachy_mini/kinematics/analytical_kinematics.py index 62cd5cb3..65ec2b5c 100644 --- a/src/reachy_mini/kinematics/analytical_kinematics.py +++ b/src/reachy_mini/kinematics/analytical_kinematics.py @@ -97,7 +97,7 @@ def fk( if no_iterations < 1: raise ValueError("no_iterations must be at least 1") - + T_world_platform = None for _ in range(no_iterations): T_world_platform = np.array( From 723652d44b756d279624b41266120d06104435c6 Mon Sep 17 00:00:00 2001 From: gospar Date: Wed, 22 Oct 2025 10:53:20 +0200 Subject: [PATCH 05/15] update for mypy --- .../kinematics/analytical_kinematics.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/reachy_mini/kinematics/analytical_kinematics.py b/src/reachy_mini/kinematics/analytical_kinematics.py index 65ec2b5c..5ea41b9f 100644 --- a/src/reachy_mini/kinematics/analytical_kinematics.py +++ b/src/reachy_mini/kinematics/analytical_kinematics.py @@ -46,13 +46,13 @@ def __init__(self) -> None: for motor in self.motors: self.kin.add_branch( motor["branch_position"], - np.linalg.inv(motor["T_motor_world"]), # type: ignore[arg-type] + np.linalg.inv(motor["T_motor_world"]), 1 if motor["solution"] else -1, ) sleep_head_pose = SLEEP_HEAD_POSE.copy() sleep_head_pose[:3, 3][2] += self.head_z_offset - self.kin.reset_forward_kinematics(sleep_head_pose) # type: ignore[arg-type] + self.kin.reset_forward_kinematics(sleep_head_pose) def ik( self, @@ -65,8 +65,6 @@ def ik( check_collision and no_iterations are not used by AnalyticalKinematics. We keep them for compatibility with the other kinematics engines """ - # import time - # k = time.time() _pose = pose.copy() _pose[:3, 3][2] += self.head_z_offset @@ -77,9 +75,9 @@ def ik( reachy_joints = self.kin.inverse_kinematics_safe(_pose, body_yaw = body_yaw, max_relative_yaw = np.deg2rad(65), - max_body_yaw = np.deg2rad(160)) # type: ignore[arg-type] - # print("IK time {0:.3f}us".format((time.time() - k)*1e6)) - return np.array(reachy_joints) # type: ignore[arg-type] + max_body_yaw = np.deg2rad(160)) + + return np.array(reachy_joints) def fk( self, @@ -97,7 +95,7 @@ def fk( if no_iterations < 1: raise ValueError("no_iterations must be at least 1") - + T_world_platform = None for _ in range(no_iterations): T_world_platform = np.array( From 617f8cdab17c239cde0c8667fbc821d2d30662f3 Mon Sep 17 00:00:00 2001 From: gospar Date: Wed, 22 Oct 2025 10:57:34 +0200 Subject: [PATCH 06/15] ignore arg type --- src/reachy_mini/kinematics/analytical_kinematics.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/reachy_mini/kinematics/analytical_kinematics.py b/src/reachy_mini/kinematics/analytical_kinematics.py index 5ea41b9f..43c4fcde 100644 --- a/src/reachy_mini/kinematics/analytical_kinematics.py +++ b/src/reachy_mini/kinematics/analytical_kinematics.py @@ -46,13 +46,13 @@ def __init__(self) -> None: for motor in self.motors: self.kin.add_branch( motor["branch_position"], - np.linalg.inv(motor["T_motor_world"]), + np.linalg.inv(motor["T_motor_world"]), # type: ignore[arg-type] 1 if motor["solution"] else -1, ) sleep_head_pose = SLEEP_HEAD_POSE.copy() sleep_head_pose[:3, 3][2] += self.head_z_offset - self.kin.reset_forward_kinematics(sleep_head_pose) + self.kin.reset_forward_kinematics(sleep_head_pose) # type: ignore[arg-type] def ik( self, @@ -72,7 +72,7 @@ def ik( # stay within the mechanical limits (max_body_yaw) # additionally it makes sure the the relative yaw between the body and the head # stays within the mechanical limits (max_relative_yaw) - reachy_joints = self.kin.inverse_kinematics_safe(_pose, + reachy_joints = self.kin.inverse_kinematics_safe(_pose, # type: ignore[arg-type] body_yaw = body_yaw, max_relative_yaw = np.deg2rad(65), max_body_yaw = np.deg2rad(160)) From 4ef630a97f15234006c121cd48b20da4c5fdd497 Mon Sep 17 00:00:00 2001 From: gospar Date: Thu, 23 Oct 2025 19:01:27 +0200 Subject: [PATCH 07/15] inital support for collision! --- .../daemon/backend/mujoco/backend copy.py | 312 ++++++++++++ .../daemon/backend/mujoco/backend.py | 22 + .../reachy_mini/mjcf/reachy_mini copy 2.xml | 450 ++++++++++++++++++ .../reachy_mini/mjcf/reachy_mini copy.xml | 448 +++++++++++++++++ .../reachy_mini/mjcf/reachy_mini.xml | 12 +- .../reachy_mini/mjcf/reachy_mini.xml.old | 440 +++++++++++++++++ 6 files changed, 1683 insertions(+), 1 deletion(-) create mode 100644 src/reachy_mini/daemon/backend/mujoco/backend copy.py create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy 2.xml create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy.xml create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.old diff --git a/src/reachy_mini/daemon/backend/mujoco/backend copy.py b/src/reachy_mini/daemon/backend/mujoco/backend copy.py new file mode 100644 index 00000000..881ce03b --- /dev/null +++ b/src/reachy_mini/daemon/backend/mujoco/backend copy.py @@ -0,0 +1,312 @@ +"""Mujoco Backend for Reachy Mini. + +This module provides the MujocoBackend class for simulating the Reachy Mini robot using the MuJoCo physics engine. + +It includes methods for running the simulation, getting joint positions, and controlling the robot's joints. + +""" + +import json +import time +from dataclasses import dataclass +from importlib.resources import files +from threading import Thread +from typing import Optional + +import mujoco +import mujoco.viewer +import numpy as np + +import reachy_mini +from reachy_mini.daemon.backend.abstract import Backend +from reachy_mini.daemon.backend.mujoco.utils import ( + get_actuator_names, + get_joint_addr_from_name, + get_joint_id_from_name, +) +from reachy_mini.daemon.backend.mujoco.video_udp import UDPJPEGFrameSender + + +class MujocoBackend(Backend): + """Simulated Reachy Mini using MuJoCo.""" + + def __init__(self, scene="empty", check_collision: bool = False): + """Initialize the MujocoBackend with a specified scene. + + Args: + scene (str): The name of the scene to load. Default is "empty". + check_collision (bool): If True, enable collision checking. Default is False. + + """ + super().__init__(check_collision=check_collision) + + from reachy_mini.reachy_mini import ( + SLEEP_ANTENNAS_JOINT_POSITIONS, + SLEEP_HEAD_JOINT_POSITIONS, + ) + + self._SLEEP_ANTENNAS_JOINT_POSITIONS = SLEEP_ANTENNAS_JOINT_POSITIONS + self._SLEEP_HEAD_JOINT_POSITIONS = SLEEP_HEAD_JOINT_POSITIONS + + mjcf_root_path = str( + files(reachy_mini).joinpath("descriptions/reachy_mini/mjcf/") + ) + self.model = mujoco.MjModel.from_xml_path( # type: ignore + f"{mjcf_root_path}/scenes/{scene}.xml" + ) + self.data = mujoco.MjData(self.model) # type: ignore + self.model.opt.timestep = 0.002 # s, simulation timestep, 500hz + self.decimation = 10 # -> 50hz control loop + self.rendering_timestep = 0.04 # s, rendering loop # 25Hz + + self.camera_id = mujoco.mj_name2id( # type: ignore + self.model, + mujoco.mjtObj.mjOBJ_CAMERA, # type: ignore + "eye_camera", + ) + + self.head_id = mujoco.mj_name2id( # type: ignore + self.model, + mujoco.mjtObj.mjOBJ_BODY, # type: ignore + "pp01063_stewart_plateform", + ) + + self.platform_to_head_transform = np.array( + [ + [8.66025292e-01, 5.00000194e-01, -1.83660327e-06, -1.34282000e-02], + [5.55111512e-16, -3.67320510e-06, -1.00000000e00, -1.20000000e-03], + [-5.00000194e-01, 8.66025292e-01, -3.18108852e-06, 3.65883000e-02], + [0, 0, 0, 1.00000000e00], + ] + ) + # remove_z_offset = np.eye(4) + # remove_z_offset[2, 3] = -0.177 + # self.platform_to_head_transform = self.platform_to_head_transform @ remove_z_offset + + self.current_head_pose = np.eye(4) + + # print("Joints in the model:") + # for i in range(self.model.njoint): + # name = mujoco.mj_id2joint(self.model, i) + # print(f" {i}: {name}") + + self.joint_names = get_actuator_names(self.model) + + self.joint_ids = [ + get_joint_id_from_name(self.model, n) for n in self.joint_names + ] + self.joint_qpos_addr = [ + get_joint_addr_from_name(self.model, n) for n in self.joint_names + ] + + # disable the collisions by default + self.model.geom_contype[13] = 0 # head capsule + self.model.geom_conaffinity[13] = 0 + self.model.geom_contype[80] = 0 # top of the torso + self.model.geom_conaffinity[80] = 0 + + def rendering_loop(self): + """Offline Rendering loop for the Mujoco simulation. + + Capture the image from the virtual Reachy's camera and send it over UDP. + """ + streamer_udp = UDPJPEGFrameSender() + camera_size = (1280, 720) + offscreen_renderer = mujoco.Renderer( + self.model, height=camera_size[1], width=camera_size[0] + ) + while not self.should_stop.is_set(): + start_t = time.time() + offscreen_renderer.update_scene(self.data, self.camera_id) + im = offscreen_renderer.render() + streamer_udp.send_frame(im) + + took = time.time() - start_t + time.sleep(max(0, self.rendering_timestep - took)) + + + + def run(self): + """Run the Mujoco simulation with a viewer. + + This method initializes the viewer and enters the main simulation loop. + It updates the joint positions at a rate and publishes the joint positions. + """ + step = 1 + with mujoco.viewer.launch_passive( + self.model, self.data, show_left_ui=False, show_right_ui=False + ) as viewer: + with viewer.lock(): + viewer.cam.type = mujoco.mjtCamera.mjCAMERA_FREE # type: ignore + viewer.cam.distance = 0.8 # ≃ ||pos - lookat|| + viewer.cam.azimuth = 160 # degrees + viewer.cam.elevation = -20 # degrees + viewer.cam.lookat[:] = [0, 0, 0.15] + + # force one render with your new camera + mujoco.mj_step(self.model, self.data) # type: ignore + viewer.sync() + + # im = self.get_camera() + # self.streamer_udp.send_frame(im) + with viewer.lock(): + self.data.qpos[self.joint_qpos_addr] = np.array( + self._SLEEP_HEAD_JOINT_POSITIONS + + self._SLEEP_ANTENNAS_JOINT_POSITIONS + ).reshape(-1, 1) + self.data.ctrl[:] = np.array( + self._SLEEP_HEAD_JOINT_POSITIONS + + self._SLEEP_ANTENNAS_JOINT_POSITIONS + ) + + # recompute all kinematics, collisions, etc. + mujoco.mj_forward(self.model, self.data) # type: ignore + + for i in range(20): + # one more frame so the viewer shows your startup pose + mujoco.mj_step(self.model, self.data) # type: ignore + viewer.sync() + + rendering_thread = Thread(target=self.rendering_loop, daemon=True) + rendering_thread.start() + + + #if self.check_collision: + # enable collisions + self.model.geom_contype[13] = 1 # head capsule + self.model.geom_conaffinity[13] = 1 + self.model.geom_contype[80] = 1 # top of the torso + self.model.geom_conaffinity[80] = 1 + + mujoco.mj_step(self.model, self.data) + + + + # 3) now enter your normal loop + while not self.should_stop.is_set(): + start_t = time.time() + + if step % self.decimation == 0: + # update the current states + self.current_head_joint_positions = ( + self.get_present_head_joint_positions() + ) + self.current_antenna_joint_positions = ( + self.get_present_antenna_joint_positions() + ) + self.current_head_pose = self.get_mj_present_head_pose() + + # Update the target head joint positions from IK if necessary + # - does nothing if the targets did not change + if self.ik_required: + self.update_target_head_joints_from_ik( + self.target_head_pose, self.target_body_yaw + ) + + if self.target_head_joint_positions is not None: + self.data.ctrl[:7] = self.target_head_joint_positions + if self.target_antenna_joint_positions is not None: + self.data.ctrl[-2:] = self.target_antenna_joint_positions + + if ( + self.joint_positions_publisher is not None + and self.pose_publisher is not None + ): + self.joint_positions_publisher.put( + json.dumps( + { + "head_joint_positions": self.current_head_joint_positions, + "antennas_joint_positions": self.current_antenna_joint_positions, + } + ).encode("utf-8") + ) + self.pose_publisher.put( + json.dumps( + { + "head_pose": self.get_present_head_pose().tolist(), + } + ).encode("utf-8") + ) + viewer.sync() + + mujoco.mj_step(self.model, self.data) # type: ignore + + took = time.time() - start_t + time.sleep(max(0, self.model.opt.timestep - took)) + # print(f"Step {step}: took {took*1000:.1f}ms") + step += 1 + self.ready.set() + + def get_mj_present_head_pose(self) -> np.ndarray: + """Get the current head pose from the Mujoco simulation. + + Returns: + np.ndarray: The current head pose as a 4x4 transformation matrix. + + """ + mj_current_head_pose = np.eye(4) + mj_current_head_pose[:3, :3] = self.data.xmat[self.head_id].reshape(3, 3) + mj_current_head_pose[:3, 3] = self.data.xpos[self.head_id] + mj_current_head_pose = mj_current_head_pose @ self.platform_to_head_transform + mj_current_head_pose[2, 3] -= 0.177 + return mj_current_head_pose + + def close(self) -> None: + """Close the Mujoco backend.""" + # TODO Do something in mujoco here ? + pass + + def get_status(self) -> "MujocoBackendStatus": + """Get the status of the Mujoco backend. + + Returns: + dict: An empty dictionary as the Mujoco backend does not have a specific status to report. + + """ + return MujocoBackendStatus() + + def get_present_head_joint_positions(self): + """Get the current joint positions of the head.""" + return self.data.qpos[self.joint_qpos_addr[:7]].flatten().tolist() + + def get_present_antenna_joint_positions(self): + """Get the current joint positions of the antennas.""" + return self.data.qpos[self.joint_qpos_addr[-2:]].flatten().tolist() + + def enable_motors(self) -> None: + """Enable the motors. + + Does nothing in the Mujoco backend as it does not have a concept of enabling/disabling motors. + """ + pass + + def disable_motors(self) -> None: + """Disable the motors. + + Does nothing in the Mujoco backend as it does not have a concept of enabling/disabling motors. + """ + pass + + def set_head_operation_mode(self, mode: int) -> None: + """Set mode of operation for the head. + + This does nothing in the Mujoco backend as it does not have a concept of operation modes. + """ + pass + + def set_antennas_operation_mode(self, mode: int) -> None: + """Set mode of operation for the antennas. + + This does nothing in the Mujoco backend as it does not have a concept of operation modes. + """ + pass + + +@dataclass +class MujocoBackendStatus: + """Dataclass to represent the status of the Mujoco backend. + + Empty for now, as the Mujoco backend does not have a specific status to report. + """ + + error: Optional[str] = None diff --git a/src/reachy_mini/daemon/backend/mujoco/backend.py b/src/reachy_mini/daemon/backend/mujoco/backend.py index aba69eaa..1b855aa2 100644 --- a/src/reachy_mini/daemon/backend/mujoco/backend.py +++ b/src/reachy_mini/daemon/backend/mujoco/backend.py @@ -105,6 +105,20 @@ def __init__( self.joint_qpos_addr = [ get_joint_addr_from_name(self.model, n) for n in self.joint_names ] + + self.col_inds = [] + for i,type in enumerate(self.model.geom_contype): + if type != 0: + print(f"Geom {i} : contype={self.model.geom_contype[i]}, conaffinity={self.model.geom_conaffinity[i]}") + self.col_inds.append(i) + self.model.geom_contype[i] = 0 + self.model.geom_conaffinity[i] = 0 + + # # disable the collisions by default + # self.model.geom_contype[13] = 0 # head capsule + # self.model.geom_conaffinity[13] = 0 + # self.model.geom_contype[80] = 0 # top of the torso + # self.model.geom_conaffinity[80] = 0 def rendering_loop(self) -> None: """Offline Rendering loop for the Mujoco simulation. @@ -162,6 +176,14 @@ def run(self) -> None: # recompute all kinematics, collisions, etc. mujoco.mj_forward(self.model, self.data) + for i in range(100): + mujoco.mj_step(self.model, self.data) + + # enable collisions + for i in self.col_inds: + self.model.geom_contype[i] = 1 + self.model.geom_conaffinity[i] = 1 + # one more frame so the viewer shows your startup pose mujoco.mj_step(self.model, self.data) if not self.headless: diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy 2.xml b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy 2.xml new file mode 100644 index 00000000..8f8ccd2c --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy 2.xml @@ -0,0 +1,450 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy.xml b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy.xml new file mode 100644 index 00000000..a97dbc09 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy.xml @@ -0,0 +1,448 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml index bf5dafa5..83ee966a 100644 --- a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml @@ -11,7 +11,7 @@ - + @@ -75,6 +75,11 @@ + + + + + @@ -471,9 +476,14 @@ resolution="1280 720" fovy="80" /> + + + + + diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.old b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.old new file mode 100644 index 00000000..529ebb57 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.old @@ -0,0 +1,440 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From c20106309637c7ded9dc1e0c25304630031482ab Mon Sep 17 00:00:00 2001 From: gospar Date: Fri, 24 Oct 2025 10:26:25 +0200 Subject: [PATCH 08/15] relatively good for now --- examples/gui_demos/mini_head_lookat_gui.py | 100 ++++ .../{ => gui_demos}/mini_head_position_gui.py | 5 - .../daemon/backend/mujoco/backend copy.py | 312 ------------ .../daemon/backend/mujoco/backend.py | 16 +- .../reachy_mini/mjcf/joints_properties.xml | 4 +- .../reachy_mini/mjcf/reachy_mini copy 2.xml | 450 ------------------ .../reachy_mini/mjcf/reachy_mini copy.xml | 448 ----------------- .../reachy_mini/mjcf/reachy_mini.xml | 19 +- .../reachy_mini/mjcf/reachy_mini.xml.old | 440 ----------------- .../kinematics/placo_kinematics.py | 10 +- 10 files changed, 124 insertions(+), 1680 deletions(-) create mode 100644 examples/gui_demos/mini_head_lookat_gui.py rename examples/{ => gui_demos}/mini_head_position_gui.py (93%) delete mode 100644 src/reachy_mini/daemon/backend/mujoco/backend copy.py delete mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy 2.xml delete mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy.xml delete mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.old diff --git a/examples/gui_demos/mini_head_lookat_gui.py b/examples/gui_demos/mini_head_lookat_gui.py new file mode 100644 index 00000000..035c5148 --- /dev/null +++ b/examples/gui_demos/mini_head_lookat_gui.py @@ -0,0 +1,100 @@ +"""Reachy Mini Head Position GUI Example.""" + +import time +import tkinter as tk + +import numpy as np +from scipy.spatial.transform import Rotation as R + +from reachy_mini import ReachyMini +from reachy_mini.utils import create_head_pose + +def main(): + """Run a GUI to set the head position and orientation of Reachy Mini.""" + with ReachyMini(media_backend="no_media") as mini: + t0 = time.time() + + root = tk.Tk() + root.title("Set Look At XYZ Position") + + # Add sliders for X, Y, Z position + x_var = tk.DoubleVar(value=0.0) + y_var = tk.DoubleVar(value=0.0) + z_var = tk.DoubleVar(value=0.0) + + tk.Label(root, text="X (m):").grid(row=0, column=0) + tk.Scale( + root, + variable=x_var, + from_=-0.2, + to=0.2, + resolution=0.001, + orient=tk.HORIZONTAL, + length=200, + ).grid(row=0, column=1) + tk.Label(root, text="Y (m):").grid(row=1, column=0) + tk.Scale( + root, + variable=y_var, + from_=-0.2, + to=0.2, + resolution=0.001, + orient=tk.HORIZONTAL, + length=200, + ).grid(row=1, column=1) + tk.Label(root, text="Z (m):").grid(row=2, column=0) + tk.Scale( + root, + variable=z_var, + from_=-0.2, + to=0.2, + resolution=0.001, + orient=tk.HORIZONTAL, + length=200, + ).grid(row=2, column=1) + + tk.Label(root, text="Body Yaw (deg):").grid(row=3, column=0) + body_yaw_var = tk.DoubleVar(value=0.0) + tk.Scale( + root, + variable=body_yaw_var, + from_=-180, + to=180, + resolution=1.0, + orient=tk.HORIZONTAL, + length=200, + ).grid(row=3, column=1) + + mini.goto_target(create_head_pose(), antennas=[0.0, 0.0], duration=1.0) + + # Run the GUI in a non-blocking way + root.update() + + try: + while True: + t = time.time() - t0 + target = np.deg2rad(30) * np.sin(2 * np.pi * 0.5 * t) + + head = np.eye(4) + head[:3, 3] = [0, 0, 0.0] + + head = mini.look_at_world(x_var.get(), y_var.get(), z_var.get(), duration=0.3, perform_movement=False) + + root.update() + + mini.set_target( + head=head, + body_yaw=np.deg2rad(body_yaw_var.get()), + antennas=np.array([target, -target]), + ) + + + + except KeyboardInterrupt: + pass + finally: + root.destroy() + + +if __name__ == "__main__": + main() diff --git a/examples/mini_head_position_gui.py b/examples/gui_demos/mini_head_position_gui.py similarity index 93% rename from examples/mini_head_position_gui.py rename to examples/gui_demos/mini_head_position_gui.py index 7b0f732d..d6df8dbd 100644 --- a/examples/mini_head_position_gui.py +++ b/examples/gui_demos/mini_head_position_gui.py @@ -83,11 +83,6 @@ def main(): length=200, ).grid(row=6, column=1) - # add a checkbox to enable/disable collision checking - collision_check_var = tk.BooleanVar(value=False) - tk.Checkbutton(root, text="Check Collision", variable=collision_check_var).grid( - row=7, column=1 - ) mini.goto_target(create_head_pose(), antennas=[0.0, 0.0], duration=1.0) diff --git a/src/reachy_mini/daemon/backend/mujoco/backend copy.py b/src/reachy_mini/daemon/backend/mujoco/backend copy.py deleted file mode 100644 index 881ce03b..00000000 --- a/src/reachy_mini/daemon/backend/mujoco/backend copy.py +++ /dev/null @@ -1,312 +0,0 @@ -"""Mujoco Backend for Reachy Mini. - -This module provides the MujocoBackend class for simulating the Reachy Mini robot using the MuJoCo physics engine. - -It includes methods for running the simulation, getting joint positions, and controlling the robot's joints. - -""" - -import json -import time -from dataclasses import dataclass -from importlib.resources import files -from threading import Thread -from typing import Optional - -import mujoco -import mujoco.viewer -import numpy as np - -import reachy_mini -from reachy_mini.daemon.backend.abstract import Backend -from reachy_mini.daemon.backend.mujoco.utils import ( - get_actuator_names, - get_joint_addr_from_name, - get_joint_id_from_name, -) -from reachy_mini.daemon.backend.mujoco.video_udp import UDPJPEGFrameSender - - -class MujocoBackend(Backend): - """Simulated Reachy Mini using MuJoCo.""" - - def __init__(self, scene="empty", check_collision: bool = False): - """Initialize the MujocoBackend with a specified scene. - - Args: - scene (str): The name of the scene to load. Default is "empty". - check_collision (bool): If True, enable collision checking. Default is False. - - """ - super().__init__(check_collision=check_collision) - - from reachy_mini.reachy_mini import ( - SLEEP_ANTENNAS_JOINT_POSITIONS, - SLEEP_HEAD_JOINT_POSITIONS, - ) - - self._SLEEP_ANTENNAS_JOINT_POSITIONS = SLEEP_ANTENNAS_JOINT_POSITIONS - self._SLEEP_HEAD_JOINT_POSITIONS = SLEEP_HEAD_JOINT_POSITIONS - - mjcf_root_path = str( - files(reachy_mini).joinpath("descriptions/reachy_mini/mjcf/") - ) - self.model = mujoco.MjModel.from_xml_path( # type: ignore - f"{mjcf_root_path}/scenes/{scene}.xml" - ) - self.data = mujoco.MjData(self.model) # type: ignore - self.model.opt.timestep = 0.002 # s, simulation timestep, 500hz - self.decimation = 10 # -> 50hz control loop - self.rendering_timestep = 0.04 # s, rendering loop # 25Hz - - self.camera_id = mujoco.mj_name2id( # type: ignore - self.model, - mujoco.mjtObj.mjOBJ_CAMERA, # type: ignore - "eye_camera", - ) - - self.head_id = mujoco.mj_name2id( # type: ignore - self.model, - mujoco.mjtObj.mjOBJ_BODY, # type: ignore - "pp01063_stewart_plateform", - ) - - self.platform_to_head_transform = np.array( - [ - [8.66025292e-01, 5.00000194e-01, -1.83660327e-06, -1.34282000e-02], - [5.55111512e-16, -3.67320510e-06, -1.00000000e00, -1.20000000e-03], - [-5.00000194e-01, 8.66025292e-01, -3.18108852e-06, 3.65883000e-02], - [0, 0, 0, 1.00000000e00], - ] - ) - # remove_z_offset = np.eye(4) - # remove_z_offset[2, 3] = -0.177 - # self.platform_to_head_transform = self.platform_to_head_transform @ remove_z_offset - - self.current_head_pose = np.eye(4) - - # print("Joints in the model:") - # for i in range(self.model.njoint): - # name = mujoco.mj_id2joint(self.model, i) - # print(f" {i}: {name}") - - self.joint_names = get_actuator_names(self.model) - - self.joint_ids = [ - get_joint_id_from_name(self.model, n) for n in self.joint_names - ] - self.joint_qpos_addr = [ - get_joint_addr_from_name(self.model, n) for n in self.joint_names - ] - - # disable the collisions by default - self.model.geom_contype[13] = 0 # head capsule - self.model.geom_conaffinity[13] = 0 - self.model.geom_contype[80] = 0 # top of the torso - self.model.geom_conaffinity[80] = 0 - - def rendering_loop(self): - """Offline Rendering loop for the Mujoco simulation. - - Capture the image from the virtual Reachy's camera and send it over UDP. - """ - streamer_udp = UDPJPEGFrameSender() - camera_size = (1280, 720) - offscreen_renderer = mujoco.Renderer( - self.model, height=camera_size[1], width=camera_size[0] - ) - while not self.should_stop.is_set(): - start_t = time.time() - offscreen_renderer.update_scene(self.data, self.camera_id) - im = offscreen_renderer.render() - streamer_udp.send_frame(im) - - took = time.time() - start_t - time.sleep(max(0, self.rendering_timestep - took)) - - - - def run(self): - """Run the Mujoco simulation with a viewer. - - This method initializes the viewer and enters the main simulation loop. - It updates the joint positions at a rate and publishes the joint positions. - """ - step = 1 - with mujoco.viewer.launch_passive( - self.model, self.data, show_left_ui=False, show_right_ui=False - ) as viewer: - with viewer.lock(): - viewer.cam.type = mujoco.mjtCamera.mjCAMERA_FREE # type: ignore - viewer.cam.distance = 0.8 # ≃ ||pos - lookat|| - viewer.cam.azimuth = 160 # degrees - viewer.cam.elevation = -20 # degrees - viewer.cam.lookat[:] = [0, 0, 0.15] - - # force one render with your new camera - mujoco.mj_step(self.model, self.data) # type: ignore - viewer.sync() - - # im = self.get_camera() - # self.streamer_udp.send_frame(im) - with viewer.lock(): - self.data.qpos[self.joint_qpos_addr] = np.array( - self._SLEEP_HEAD_JOINT_POSITIONS - + self._SLEEP_ANTENNAS_JOINT_POSITIONS - ).reshape(-1, 1) - self.data.ctrl[:] = np.array( - self._SLEEP_HEAD_JOINT_POSITIONS - + self._SLEEP_ANTENNAS_JOINT_POSITIONS - ) - - # recompute all kinematics, collisions, etc. - mujoco.mj_forward(self.model, self.data) # type: ignore - - for i in range(20): - # one more frame so the viewer shows your startup pose - mujoco.mj_step(self.model, self.data) # type: ignore - viewer.sync() - - rendering_thread = Thread(target=self.rendering_loop, daemon=True) - rendering_thread.start() - - - #if self.check_collision: - # enable collisions - self.model.geom_contype[13] = 1 # head capsule - self.model.geom_conaffinity[13] = 1 - self.model.geom_contype[80] = 1 # top of the torso - self.model.geom_conaffinity[80] = 1 - - mujoco.mj_step(self.model, self.data) - - - - # 3) now enter your normal loop - while not self.should_stop.is_set(): - start_t = time.time() - - if step % self.decimation == 0: - # update the current states - self.current_head_joint_positions = ( - self.get_present_head_joint_positions() - ) - self.current_antenna_joint_positions = ( - self.get_present_antenna_joint_positions() - ) - self.current_head_pose = self.get_mj_present_head_pose() - - # Update the target head joint positions from IK if necessary - # - does nothing if the targets did not change - if self.ik_required: - self.update_target_head_joints_from_ik( - self.target_head_pose, self.target_body_yaw - ) - - if self.target_head_joint_positions is not None: - self.data.ctrl[:7] = self.target_head_joint_positions - if self.target_antenna_joint_positions is not None: - self.data.ctrl[-2:] = self.target_antenna_joint_positions - - if ( - self.joint_positions_publisher is not None - and self.pose_publisher is not None - ): - self.joint_positions_publisher.put( - json.dumps( - { - "head_joint_positions": self.current_head_joint_positions, - "antennas_joint_positions": self.current_antenna_joint_positions, - } - ).encode("utf-8") - ) - self.pose_publisher.put( - json.dumps( - { - "head_pose": self.get_present_head_pose().tolist(), - } - ).encode("utf-8") - ) - viewer.sync() - - mujoco.mj_step(self.model, self.data) # type: ignore - - took = time.time() - start_t - time.sleep(max(0, self.model.opt.timestep - took)) - # print(f"Step {step}: took {took*1000:.1f}ms") - step += 1 - self.ready.set() - - def get_mj_present_head_pose(self) -> np.ndarray: - """Get the current head pose from the Mujoco simulation. - - Returns: - np.ndarray: The current head pose as a 4x4 transformation matrix. - - """ - mj_current_head_pose = np.eye(4) - mj_current_head_pose[:3, :3] = self.data.xmat[self.head_id].reshape(3, 3) - mj_current_head_pose[:3, 3] = self.data.xpos[self.head_id] - mj_current_head_pose = mj_current_head_pose @ self.platform_to_head_transform - mj_current_head_pose[2, 3] -= 0.177 - return mj_current_head_pose - - def close(self) -> None: - """Close the Mujoco backend.""" - # TODO Do something in mujoco here ? - pass - - def get_status(self) -> "MujocoBackendStatus": - """Get the status of the Mujoco backend. - - Returns: - dict: An empty dictionary as the Mujoco backend does not have a specific status to report. - - """ - return MujocoBackendStatus() - - def get_present_head_joint_positions(self): - """Get the current joint positions of the head.""" - return self.data.qpos[self.joint_qpos_addr[:7]].flatten().tolist() - - def get_present_antenna_joint_positions(self): - """Get the current joint positions of the antennas.""" - return self.data.qpos[self.joint_qpos_addr[-2:]].flatten().tolist() - - def enable_motors(self) -> None: - """Enable the motors. - - Does nothing in the Mujoco backend as it does not have a concept of enabling/disabling motors. - """ - pass - - def disable_motors(self) -> None: - """Disable the motors. - - Does nothing in the Mujoco backend as it does not have a concept of enabling/disabling motors. - """ - pass - - def set_head_operation_mode(self, mode: int) -> None: - """Set mode of operation for the head. - - This does nothing in the Mujoco backend as it does not have a concept of operation modes. - """ - pass - - def set_antennas_operation_mode(self, mode: int) -> None: - """Set mode of operation for the antennas. - - This does nothing in the Mujoco backend as it does not have a concept of operation modes. - """ - pass - - -@dataclass -class MujocoBackendStatus: - """Dataclass to represent the status of the Mujoco backend. - - Empty for now, as the Mujoco backend does not have a specific status to report. - """ - - error: Optional[str] = None diff --git a/src/reachy_mini/daemon/backend/mujoco/backend.py b/src/reachy_mini/daemon/backend/mujoco/backend.py index 1b855aa2..9f023866 100644 --- a/src/reachy_mini/daemon/backend/mujoco/backend.py +++ b/src/reachy_mini/daemon/backend/mujoco/backend.py @@ -92,11 +92,6 @@ def __init__( self.current_head_pose = np.eye(4) - # print("Joints in the model:") - # for i in range(self.model.njoint): - # name = mujoco.mj_id2joint(self.model, i) - # print(f" {i}: {name}") - self.joint_names = get_actuator_names(self.model) self.joint_ids = [ @@ -114,11 +109,6 @@ def __init__( self.model.geom_contype[i] = 0 self.model.geom_conaffinity[i] = 0 - # # disable the collisions by default - # self.model.geom_contype[13] = 0 # head capsule - # self.model.geom_conaffinity[13] = 0 - # self.model.geom_contype[80] = 0 # top of the torso - # self.model.geom_conaffinity[80] = 0 def rendering_loop(self) -> None: """Offline Rendering loop for the Mujoco simulation. @@ -183,6 +173,10 @@ def run(self) -> None: for i in self.col_inds: self.model.geom_contype[i] = 1 self.model.geom_conaffinity[i] = 1 + + + for i in range(100): + mujoco.mj_step(self.model, self.data) # one more frame so the viewer shows your startup pose mujoco.mj_step(self.model, self.data) @@ -252,7 +246,7 @@ def run(self) -> None: took = time.time() - start_t time.sleep(max(0, self.model.opt.timestep - took)) - # print(f"Step {step}: took {took*1000:.1f}ms") + #print(f"Step {step}: took {took*1e6:.1f}us") step += 1 if not self.headless: diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/joints_properties.xml b/src/reachy_mini/descriptions/reachy_mini/mjcf/joints_properties.xml index 0d7260b4..7a166408 100644 --- a/src/reachy_mini/descriptions/reachy_mini/mjcf/joints_properties.xml +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/joints_properties.xml @@ -2,8 +2,8 @@ - - + + diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy 2.xml b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy 2.xml deleted file mode 100644 index 8f8ccd2c..00000000 --- a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy 2.xml +++ /dev/null @@ -1,450 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy.xml b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy.xml deleted file mode 100644 index a97dbc09..00000000 --- a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini copy.xml +++ /dev/null @@ -1,448 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml index 83ee966a..dc66a337 100644 --- a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml @@ -19,8 +19,8 @@ - - + + @@ -75,10 +75,15 @@ - - - - + + + + + + + + @@ -476,7 +481,7 @@ resolution="1280 720" fovy="80" /> - + diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.old b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.old deleted file mode 100644 index 529ebb57..00000000 --- a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml.old +++ /dev/null @@ -1,440 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/reachy_mini/kinematics/placo_kinematics.py b/src/reachy_mini/kinematics/placo_kinematics.py index 01896d90..5e87a9ea 100644 --- a/src/reachy_mini/kinematics/placo_kinematics.py +++ b/src/reachy_mini/kinematics/placo_kinematics.py @@ -89,7 +89,7 @@ def __init__( # This will allow independent control of the torso and the head yaw # until this constraint is reached yaw_constraint = self.ik_solver.add_yaw_constraint( - "dummy_torso_yaw", "head", np.deg2rad(65.0) + "dummy_torso_yaw", "head", np.deg2rad(55.0) ) yaw_constraint.configure("rel_yaw", "hard") @@ -105,18 +105,18 @@ def __init__( # Add a cone constraint for the head to not exceed a certain angle # This is to avoid the head from looking too far up or down self.fk_cone = self.ik_solver.add_cone_constraint( - "body_foot_3dprint", "head", np.deg2rad(40.0) + "body_foot_3dprint", "head", np.deg2rad(30.0) ) self.fk_cone.configure("cone", "hard") self.fk_yaw_constraint = self.fk_solver.add_yaw_constraint( - "dummy_torso_yaw", "head", np.deg2rad(65.0) + "dummy_torso_yaw", "head", np.deg2rad(55.0) ) self.fk_yaw_constraint.configure("rel_yaw", "hard") # Add a cone constraint for the head to not exceed a certain angle # This is to avoid the head from looking too far up or down fk_cone = self.fk_solver.add_cone_constraint( - "body_foot_3dprint", "head", np.deg2rad(40.0) + "body_foot_3dprint", "head", np.deg2rad(30.0) ) fk_cone.configure("cone", "hard") @@ -142,7 +142,7 @@ def __init__( # regularization self.ik_yaw_joint_task = self.ik_solver.add_joints_task() self.ik_yaw_joint_task.set_joints({"yaw_body": 0}) - if self.automatic_body_yaw: + if not self.automatic_body_yaw: self.ik_yaw_joint_task.configure("joints", "soft", 5e-5) else: self.ik_yaw_joint_task.configure("joints", "soft", 1.0) From 6b8ae1a4ff76a45f928e6fc3ee0d2030254f4489 Mon Sep 17 00:00:00 2001 From: gospar Date: Fri, 24 Oct 2025 10:28:50 +0200 Subject: [PATCH 09/15] ruff --- examples/gui_demos/mini_head_lookat_gui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gui_demos/mini_head_lookat_gui.py b/examples/gui_demos/mini_head_lookat_gui.py index 035c5148..fd45f296 100644 --- a/examples/gui_demos/mini_head_lookat_gui.py +++ b/examples/gui_demos/mini_head_lookat_gui.py @@ -4,11 +4,11 @@ import tkinter as tk import numpy as np -from scipy.spatial.transform import Rotation as R from reachy_mini import ReachyMini from reachy_mini.utils import create_head_pose + def main(): """Run a GUI to set the head position and orientation of Reachy Mini.""" with ReachyMini(media_backend="no_media") as mini: From 55088898325fb8e71602b99ba4a202922ba81471 Mon Sep 17 00:00:00 2001 From: gospar Date: Fri, 24 Oct 2025 10:49:09 +0200 Subject: [PATCH 10/15] remove print --- src/reachy_mini/daemon/backend/mujoco/backend.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/reachy_mini/daemon/backend/mujoco/backend.py b/src/reachy_mini/daemon/backend/mujoco/backend.py index 9f023866..1499d788 100644 --- a/src/reachy_mini/daemon/backend/mujoco/backend.py +++ b/src/reachy_mini/daemon/backend/mujoco/backend.py @@ -104,7 +104,6 @@ def __init__( self.col_inds = [] for i,type in enumerate(self.model.geom_contype): if type != 0: - print(f"Geom {i} : contype={self.model.geom_contype[i]}, conaffinity={self.model.geom_conaffinity[i]}") self.col_inds.append(i) self.model.geom_contype[i] = 0 self.model.geom_conaffinity[i] = 0 From 0647847d32b42430ee9059502591237ed49f9767 Mon Sep 17 00:00:00 2001 From: gospar Date: Mon, 27 Oct 2025 18:15:34 +0100 Subject: [PATCH 11/15] much better collision avoidance --- .../daemon/backend/mujoco/backend.py | 5 +++ .../body_top_3dprint_collider_back_0.stl | 3 ++ .../body_top_3dprint_collider_back_1.stl | 3 ++ .../body_top_3dprint_collider_back_2.stl | 3 ++ .../body_top_3dprint_collider_back_3.stl | 3 ++ .../body_top_3dprint_collider_front_0.stl | 3 ++ .../body_top_3dprint_collider_front_1.stl | 3 ++ .../body_top_3dprint_collider_front_2.stl | 3 ++ .../coarse/head_one_3dprint_collider_0.stl | 3 ++ .../fine/body_top_3dprint_collider_back_0.stl | 3 ++ .../fine/body_top_3dprint_collider_back_1.stl | 3 ++ .../fine/body_top_3dprint_collider_back_2.stl | 3 ++ .../fine/body_top_3dprint_collider_back_3.stl | 3 ++ .../body_top_3dprint_collider_front_0.stl | 3 ++ .../body_top_3dprint_collider_front_1.stl | 3 ++ .../body_top_3dprint_collider_front_2.stl | 3 ++ .../fine/head_one_3dprint_collider_0.stl | 3 ++ .../reachy_mini/mjcf/reachy_mini.xml | 37 +++++++++++-------- .../kinematics/placo_kinematics.py | 4 +- 19 files changed, 77 insertions(+), 17 deletions(-) create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/head_one_3dprint_collider_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_1.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_2.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_3.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_1.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_2.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/head_one_3dprint_collider_0.stl diff --git a/src/reachy_mini/daemon/backend/mujoco/backend.py b/src/reachy_mini/daemon/backend/mujoco/backend.py index 1499d788..6decdb55 100644 --- a/src/reachy_mini/daemon/backend/mujoco/backend.py +++ b/src/reachy_mini/daemon/backend/mujoco/backend.py @@ -185,6 +185,11 @@ def run(self) -> None: rendering_thread = Thread(target=self.rendering_loop, daemon=True) rendering_thread.start() + # Update the internal states of the IK and FK to the current configuration + # This is important to avoid jumps when starting the robot (beore wake-up) + self.head_kinematics.ik(self.get_mj_present_head_pose(), no_iterations=20) + self.head_kinematics.fk(self.get_present_head_joint_positions(), no_iterations=20) + # 3) now enter your normal loop while not self.should_stop.is_set(): start_t = time.time() diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl new file mode 100644 index 00000000..b134982c --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f92539090c8fbef3a292ffbdc6a1019828ad5e33a5b87354ad08032a59d0c35 +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl new file mode 100644 index 00000000..dc98ea93 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9186fdc67813c3b7f3fba721cbfbb14d5e6f20bcabe1897d488913b6879bfd78 +size 4784 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl new file mode 100644 index 00000000..592ecb1e --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2db1d2726afd373e145a7b3cb8340983eeff49c07f8e4057e2d4eec7f91c35df +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl new file mode 100644 index 00000000..2bea29e7 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e7916bfcdccd254c51143774575c7a0924a1a1939fd9a4755ae3b8f2c920bdc +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl new file mode 100644 index 00000000..728659d3 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94d9c386d10344ae4fa03baae3ea0ca935c8ab2a5d41352a4b4c59c3ac2fd9e1 +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl new file mode 100644 index 00000000..d296a17e --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e893cc8cd9581722ffe7798031076190cdc2264edc70694d925be5cf326b8bc2 +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl new file mode 100644 index 00000000..d990c548 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ec16d901b544cd898eb1836d4f61fc16855919bd856c82f0fd23ac180e684af +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/head_one_3dprint_collider_0.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/head_one_3dprint_collider_0.stl new file mode 100644 index 00000000..2dbfd40c --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/head_one_3dprint_collider_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ab3bd4077363b5c0196434dba82051b19ec63ec76ef93e76b28cdd1c0187ddd +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_0.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_0.stl new file mode 100644 index 00000000..6e405fc6 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c22bb171ab47155a4fe2946cd267f8e43cba901dd11d3106082bbe1848f90b4 +size 190084 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_1.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_1.stl new file mode 100644 index 00000000..34019f99 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_1.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a2c6189ab48a1b296ab5e0695363ab20021154dc7823d3eef8a188b992c1682 +size 195784 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_2.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_2.stl new file mode 100644 index 00000000..67603dad --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_2.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbdf0d34da912a29174148bd78b90e3541755f9bc20d2a5cc624e3565aef3d94 +size 78684 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_3.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_3.stl new file mode 100644 index 00000000..37d62560 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_back_3.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e7c26eb2033477e711d6ea535b955a91f443b74d21a4d8e5ed1bfb72c10c401 +size 245084 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_0.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_0.stl new file mode 100644 index 00000000..f0f3c8da --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27dcf3bcfc55a11f5fe3a6a5f01fe253fb5e9cf9d736aa9b83a44d286aeef38c +size 185384 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_1.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_1.stl new file mode 100644 index 00000000..ce58be8b --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_1.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89940a91f8e1bf1d1b7c4844bc58a8a03f5c3983cfc174573e8f60f6a47c1109 +size 182484 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_2.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_2.stl new file mode 100644 index 00000000..8964aa93 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/body_top_3dprint_collider_front_2.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ccf48cd480051da28caee941ad1e130f74cebfd2c474d5791d5e014e10fcdfd +size 219184 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/head_one_3dprint_collider_0.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/head_one_3dprint_collider_0.stl new file mode 100644 index 00000000..1d636e5f --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/fine/head_one_3dprint_collider_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a28add53d3bc49c5b7f6d9e8f8f0884bbfa1ad9fe81af5ca58f01d08a072ed9 +size 1359584 diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml index dc66a337..bb32faf5 100644 --- a/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/reachy_mini.xml @@ -75,16 +75,14 @@ - - - - - - - - - + + + + + + + + @@ -410,6 +408,7 @@ + @@ -481,14 +480,11 @@ resolution="1280 720" fovy="80" /> - - + - - - + @@ -565,6 +561,17 @@ + + + + + + + + + + + diff --git a/src/reachy_mini/kinematics/placo_kinematics.py b/src/reachy_mini/kinematics/placo_kinematics.py index 5e87a9ea..3c977bdd 100644 --- a/src/reachy_mini/kinematics/placo_kinematics.py +++ b/src/reachy_mini/kinematics/placo_kinematics.py @@ -105,7 +105,7 @@ def __init__( # Add a cone constraint for the head to not exceed a certain angle # This is to avoid the head from looking too far up or down self.fk_cone = self.ik_solver.add_cone_constraint( - "body_foot_3dprint", "head", np.deg2rad(30.0) + "body_foot_3dprint", "head", np.deg2rad(35.0) ) self.fk_cone.configure("cone", "hard") self.fk_yaw_constraint = self.fk_solver.add_yaw_constraint( @@ -116,7 +116,7 @@ def __init__( # Add a cone constraint for the head to not exceed a certain angle # This is to avoid the head from looking too far up or down fk_cone = self.fk_solver.add_cone_constraint( - "body_foot_3dprint", "head", np.deg2rad(30.0) + "body_foot_3dprint", "head", np.deg2rad(35.0) ) fk_cone.configure("cone", "hard") From a84465b4497801e2f37274f48fb4328061903033 Mon Sep 17 00:00:00 2001 From: gospar Date: Tue, 28 Oct 2025 11:05:34 +0100 Subject: [PATCH 12/15] a bit better head --- .../assets/collision/coarse/head_one_3dprint_collider_0.stl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/head_one_3dprint_collider_0.stl b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/head_one_3dprint_collider_0.stl index 2dbfd40c..b5a03639 100644 --- a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/head_one_3dprint_collider_0.stl +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/coarse/head_one_3dprint_collider_0.stl @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ab3bd4077363b5c0196434dba82051b19ec63ec76ef93e76b28cdd1c0187ddd -size 4884 +oid sha256:9ba0e5a4dc95869e16212e69fa3712ea7f021378cf76db0b1a8d2300eaab3c64 +size 6884 From 878a813b9bb3be9d54eaa7e119b29075339e1770 Mon Sep 17 00:00:00 2001 From: gospar Date: Tue, 28 Oct 2025 11:30:21 +0100 Subject: [PATCH 13/15] info in readme --- .../descriptions/reachy_mini/mjcf/assets/collision/README.m | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/README.m diff --git a/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/README.m b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/README.m new file mode 100644 index 00000000..edda0bc7 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/mjcf/assets/collision/README.m @@ -0,0 +1 @@ +Created with: https://github.com/pollen-robotics/reachy_mini_stl_convexify \ No newline at end of file From 88ec248dc6b1d9e0954f28f8b1dc72b5e25dab8f Mon Sep 17 00:00:00 2001 From: gospar Date: Thu, 30 Oct 2025 10:13:39 +0100 Subject: [PATCH 14/15] new behavior for placo and collisions --- .../urdf/assets/collision/README.m | 1 + .../body_top_3dprint_collider_back_0.stl | 3 + .../body_top_3dprint_collider_back_1.stl | 3 + .../body_top_3dprint_collider_back_2.stl | 3 + .../body_top_3dprint_collider_back_3.stl | 3 + .../body_top_3dprint_collider_front_0.stl | 3 + .../body_top_3dprint_collider_front_1.stl | 3 + .../body_top_3dprint_collider_front_2.stl | 3 + .../coarse/head_one_3dprint_collider_0.stl | 3 + .../fine/body_top_3dprint_collider_back_0.stl | 3 + .../fine/body_top_3dprint_collider_back_1.stl | 3 + .../fine/body_top_3dprint_collider_back_2.stl | 3 + .../fine/body_top_3dprint_collider_back_3.stl | 3 + .../body_top_3dprint_collider_front_0.stl | 3 + .../body_top_3dprint_collider_front_1.stl | 3 + .../body_top_3dprint_collider_front_2.stl | 3 + .../fine/head_one_3dprint_collider_0.stl | 3 + .../urdf/robot_simple_collision.urdf | 2399 +++++++++++++++++ .../kinematics/placo_kinematics.py | 58 +- 19 files changed, 2470 insertions(+), 36 deletions(-) create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/README.m create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/head_one_3dprint_collider_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_1.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_2.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_3.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_1.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_2.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/head_one_3dprint_collider_0.stl create mode 100644 src/reachy_mini/descriptions/reachy_mini/urdf/robot_simple_collision.urdf diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/README.m b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/README.m new file mode 100644 index 00000000..edda0bc7 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/README.m @@ -0,0 +1 @@ +Created with: https://github.com/pollen-robotics/reachy_mini_stl_convexify \ No newline at end of file diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl new file mode 100644 index 00000000..b134982c --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f92539090c8fbef3a292ffbdc6a1019828ad5e33a5b87354ad08032a59d0c35 +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl new file mode 100644 index 00000000..dc98ea93 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_1.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9186fdc67813c3b7f3fba721cbfbb14d5e6f20bcabe1897d488913b6879bfd78 +size 4784 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl new file mode 100644 index 00000000..592ecb1e --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_2.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2db1d2726afd373e145a7b3cb8340983eeff49c07f8e4057e2d4eec7f91c35df +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl new file mode 100644 index 00000000..2bea29e7 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_back_3.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e7916bfcdccd254c51143774575c7a0924a1a1939fd9a4755ae3b8f2c920bdc +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl new file mode 100644 index 00000000..728659d3 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94d9c386d10344ae4fa03baae3ea0ca935c8ab2a5d41352a4b4c59c3ac2fd9e1 +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl new file mode 100644 index 00000000..d296a17e --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_1.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e893cc8cd9581722ffe7798031076190cdc2264edc70694d925be5cf326b8bc2 +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl new file mode 100644 index 00000000..d990c548 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/body_top_3dprint_collider_front_2.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1ec16d901b544cd898eb1836d4f61fc16855919bd856c82f0fd23ac180e684af +size 4884 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/head_one_3dprint_collider_0.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/head_one_3dprint_collider_0.stl new file mode 100644 index 00000000..b5a03639 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/coarse/head_one_3dprint_collider_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ba0e5a4dc95869e16212e69fa3712ea7f021378cf76db0b1a8d2300eaab3c64 +size 6884 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_0.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_0.stl new file mode 100644 index 00000000..6e405fc6 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c22bb171ab47155a4fe2946cd267f8e43cba901dd11d3106082bbe1848f90b4 +size 190084 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_1.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_1.stl new file mode 100644 index 00000000..34019f99 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_1.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a2c6189ab48a1b296ab5e0695363ab20021154dc7823d3eef8a188b992c1682 +size 195784 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_2.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_2.stl new file mode 100644 index 00000000..67603dad --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_2.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cbdf0d34da912a29174148bd78b90e3541755f9bc20d2a5cc624e3565aef3d94 +size 78684 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_3.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_3.stl new file mode 100644 index 00000000..37d62560 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_back_3.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e7c26eb2033477e711d6ea535b955a91f443b74d21a4d8e5ed1bfb72c10c401 +size 245084 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_0.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_0.stl new file mode 100644 index 00000000..f0f3c8da --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27dcf3bcfc55a11f5fe3a6a5f01fe253fb5e9cf9d736aa9b83a44d286aeef38c +size 185384 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_1.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_1.stl new file mode 100644 index 00000000..ce58be8b --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_1.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89940a91f8e1bf1d1b7c4844bc58a8a03f5c3983cfc174573e8f60f6a47c1109 +size 182484 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_2.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_2.stl new file mode 100644 index 00000000..8964aa93 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/body_top_3dprint_collider_front_2.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ccf48cd480051da28caee941ad1e130f74cebfd2c474d5791d5e014e10fcdfd +size 219184 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/head_one_3dprint_collider_0.stl b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/head_one_3dprint_collider_0.stl new file mode 100644 index 00000000..1d636e5f --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/assets/collision/fine/head_one_3dprint_collider_0.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a28add53d3bc49c5b7f6d9e8f8f0884bbfa1ad9fe81af5ca58f01d08a072ed9 +size 1359584 diff --git a/src/reachy_mini/descriptions/reachy_mini/urdf/robot_simple_collision.urdf b/src/reachy_mini/descriptions/reachy_mini/urdf/robot_simple_collision.urdf new file mode 100644 index 00000000..1326b3e7 --- /dev/null +++ b/src/reachy_mini/descriptions/reachy_mini/urdf/robot_simple_collision.urdf @@ -0,0 +1,2399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/reachy_mini/kinematics/placo_kinematics.py b/src/reachy_mini/kinematics/placo_kinematics.py index 3c977bdd..fb9f0b2d 100644 --- a/src/reachy_mini/kinematics/placo_kinematics.py +++ b/src/reachy_mini/kinematics/placo_kinematics.py @@ -41,13 +41,15 @@ def __init__( ) # 0.1 degrees tolerance for the FK reached condition if not urdf_path.endswith(".urdf"): - urdf_path = f"{urdf_path}/{'robot.urdf' if check_collision else 'robot_no_collision.urdf'}" + urdf_path = f"{urdf_path}/{'robot_simple_collision.urdf' if check_collision else 'robot_no_collision.urdf'}" self.robot = placo.RobotWrapper( - urdf_path, placo.Flags.ignore_collisions + placo.Flags.collision_as_visual + urdf_path, placo.Flags.collision_as_visual + placo.Flags.ignore_collisions ) + + flags = 0 if check_collision else placo.Flags.ignore_collisions + placo.Flags.collision_as_visual self.robot_ik = placo.RobotWrapper( - urdf_path, placo.Flags.ignore_collisions + placo.Flags.collision_as_visual + urdf_path, flags ) self.ik_solver = placo.KinematicsSolver(self.robot_ik) @@ -240,6 +242,11 @@ def __init__( self.robot.update_kinematics() if self.check_collision: + ik_col = self.ik_solver.add_avoid_self_collisions_constraint() + ik_col.self_collisions_margin = 0.001 # 1mm + ik_col.self_collisions_trigger = 0.002 # 2mm + ik_col.configure("avoid_self_collisions", "hard") + # setup the collision model self.config_collision_model() @@ -396,16 +403,7 @@ def ik( self._logger.warning(f"IK solver failed: {e}, no solution found!") return None self.robot_ik.update_kinematics() - - # verify that there is no collision - if self.check_collision and self.compute_collision(): - self._logger.warning( - "IK: Collision detected, using the previous configuration..." - ) - self._update_state_to_initial(self.robot_ik) # revert to the inital state - self.robot_ik.update_kinematics() - return None - + # Get the joint angles return np.array(self._get_joint_values(self.robot_ik)) @@ -487,13 +485,6 @@ def fk( return None self.robot.update_kinematics() - if self.check_collision and self.compute_collision(): - self._logger.warning("FK: Collision detected, using the previous config...") - self._update_state_to_initial(self.robot) # revert to the previous state - self.robot.state.q = q - self.robot.update_kinematics() - # return None - # Get the head frame transformation T_world_head = self.robot.get_T_world_frame("head") T_world_head[:3, 3][2] -= self.head_z_offset # offset the height of the head @@ -505,20 +496,14 @@ def config_collision_model(self) -> None: Add collision pairs between the torso and the head colliders. """ - geom_model = self.robot.collision_model - - # name_torso_collider = "dc15_a01_case_b_dummy_10" - # names_head_colliders = ["pp01063_stewart_plateform_7", "pp01063_stewart_plateform_11"] + geom_model = self.robot_ik.collision_model - id_torso_collider = 12 # geom_model.getGeometryObjectId(name_torso_collider) - id_head_colliders = [ - 74, - 78, - ] # [geom_model.getGeometryObjectId(name) for name in names_head_colliders] + id_torso_colliders = list(range(len(geom_model.geometryObjects)-1)) + id_head_collider = len(geom_model.geometryObjects)-1 - for i in id_head_colliders: + for i in id_torso_colliders: geom_model.addCollisionPair( - pin.CollisionPair(id_torso_collider, i) + pin.CollisionPair(id_head_collider, i) ) # torso with head colliders def compute_collision(self, margin: float = 0.005) -> bool: @@ -531,17 +516,18 @@ def compute_collision(self, margin: float = 0.005) -> bool: True if there is a collision, False otherwise. """ - collision_data = self.robot.collision_model.createData() - data = self.robot.model.createData() + collision_data = self.robot_ik.collision_model.createData() + data = self.robot_ik.model.createData() # pin.computeCollisions( pin.computeDistances( - self.robot.model, + self.robot_ik.model, data, - self.robot.collision_model, + self.robot_ik.collision_model, collision_data, - self.robot.state.q, + self.robot_ik.state.q, ) + # Iterate over all collision pairs for distance_result in collision_data.distanceResults: From f5fa37a53bd76b76169bd23c262e47e1a864871e Mon Sep 17 00:00:00 2001 From: gospar Date: Thu, 30 Oct 2025 10:34:37 +0100 Subject: [PATCH 15/15] ruff stuff --- src/reachy_mini/kinematics/placo_kinematics.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/reachy_mini/kinematics/placo_kinematics.py b/src/reachy_mini/kinematics/placo_kinematics.py index fb9f0b2d..97b3321d 100644 --- a/src/reachy_mini/kinematics/placo_kinematics.py +++ b/src/reachy_mini/kinematics/placo_kinematics.py @@ -451,9 +451,6 @@ def fk( } ) - # save the initial configuration - q = self.robot.state.q.copy() - done = True # do the inital ik with 2 iterations for i in range(no_iterations):