Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,7 @@ sandbox/

.DS_Store
.aider*

examples/pinocchio/urdf (Copie)/

examples/pinocchio/urdf (Copie).zip
27 changes: 16 additions & 11 deletions pyorerun/model_components/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,22 @@ def from_file(
mesh = load(file_path)
mesh.apply_scale(scale_factor)

# assume the first geometry if multiple are present
first_key = list(mesh.geometry.keys())[0]

real_mesh = Trimesh(
vertices=mesh.geometry[first_key].vertices,
faces=mesh.geometry[first_key].faces,
vertex_normals=mesh.geometry[first_key].vertex_normals,
metadata=dict(file_name=mesh.source.file_name),
)
if "file_name" not in mesh.metadata:
mesh.metadata["file_name"] = file_path.split("/")[-1].split(".")[0]
# Handle both Scene (multiple geometries) and single Trimesh
if hasattr(mesh, "geometry") and len(mesh.geometry) > 0:
# It's a Scene with multiple geometries - merge them properly
from trimesh.util import concatenate

geometries = list(mesh.geometry.values())
real_mesh = concatenate(geometries)
real_mesh.metadata = dict(
file_name=mesh.source.file_name if hasattr(mesh, "source") else file_path.split("/")[-1]
)
else:
# It's already a single Trimesh
real_mesh = mesh
if "file_name" not in real_mesh.metadata:
real_mesh.metadata["file_name"] = file_path.split("/")[-1].split(".")[0]

return cls(name, real_mesh, transform_callable)
else:
raise ValueError(
Expand Down
6 changes: 3 additions & 3 deletions pyorerun/model_interfaces/biorbd_model_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,20 +162,20 @@ def ligament_strips(self, q: np.ndarray) -> list[list[np.ndarray]]:
@cached_property
def nb_muscles(self) -> int:
"""
Returns the number of ligaments
Returns the number of muscles
"""
return self.model.nbMuscles()

@cached_property
def muscle_names(self) -> tuple[str, ...]:
"""
Returns the names of the ligaments
Returns the names of the muscles
"""
return tuple([s.to_string() for s in self.model.muscleNames()])

def muscle_strips(self, q: np.ndarray) -> list[list[np.ndarray]]:
"""
Returns the position of the ligaments in the global reference frame
Returns the position of the muscles in the global reference frame
"""
muscles = []
self.model.updateMuscles(q, True)
Expand Down
32 changes: 28 additions & 4 deletions pyorerun/model_interfaces/pinocchio_model_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,10 @@ def __init__(self, path: str, options=None):
raise ValueError(f"Unsupported file format for Pinocchio: {path}. Expected .urdf")

self.data = self.model.createData()
self.muscles_names = [] # Pinocchio doesn't have native muscle support, so this will be empty

@classmethod
def from_pinocchio_object(cls, model: pin.Model, path: str = None, options=None):
def from_pinocchio_object(cls, model: pin.Model, path: str = None, options=None, muscles_names: list[str] = None):
"""
Create from an existing Pinocchio model object.
"""
Expand All @@ -144,8 +145,13 @@ def from_pinocchio_object(cls, model: pin.Model, path: str = None, options=None)
instance.options = options if options is not None else DisplayModelOptions()
instance._mesh_dir = Path(path).parent if path else Path.cwd()
instance.visual_model = None
instance.muscles_names = muscles_names if muscles_names is not None else []
return instance

@cached_property
def _frame_list_names(self) -> list[str]:
return [frame.name for frame in self.model.frames]

@cached_property
def name(self) -> str:
return self.model.name if hasattr(self.model, "name") else Path(self.path).stem
Expand Down Expand Up @@ -355,20 +361,36 @@ def nb_muscles(self) -> int:
"""
Pinocchio doesn't have native muscle support.
"""
return 0
return len(self.muscles_names)

@cached_property
def muscle_names(self) -> tuple[str, ...]:
"""
Pinocchio doesn't have native muscle support.
"""
return tuple()
return tuple(self.muscles_names)

def muscle_strips(self, q: np.ndarray) -> list[list[np.ndarray]]:
"""
Pinocchio doesn't have native muscle support.
"""
return []
pin.forwardKinematics(self.model, self.data, q)
pin.updateFramePlacements(self.model, self.data)

muscles = []
for idx in range(self.nb_muscles):
muscle_name = self.muscle_names[idx]
muscle_frames = [
f_name for f_name in self._frame_list_names if muscle_name == f_name.split("-")[0]
] # assume muscle frames are named like "muscleName-1", "muscleName-2", etc.
muscle_strip = []
print(f"Muscle {muscle_name} frames: {muscle_frames}")
for i in range(len(muscle_frames)):
f1_id = self.model.getFrameId(muscle_frames[i])
frame_location = self.data.oMf[f1_id].translation
muscle_strip.append(frame_location)
muscles.append(muscle_strip)
return muscles

@cached_property
def gravity(self) -> np.ndarray:
Expand Down Expand Up @@ -443,6 +465,7 @@ def from_pinocchio_object(
collision_model: pin.GeometryModel = None,
path: str = None,
options=None,
muscles_names: list[str] = None,
):
"""
Create from existing Pinocchio objects.
Expand All @@ -455,6 +478,7 @@ def from_pinocchio_object(
instance.path = path if path else "pinocchio_model"
instance.options = options if options is not None else DisplayModelOptions()
instance._mesh_dir = Path(path).parent if path else Path.cwd()
instance.muscles_names = muscles_names if muscles_names is not None else []
return instance

@cached_property
Expand Down
1 change: 0 additions & 1 deletion pyorerun/phase_rerun.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ def rerun_by_frame(
if init:
spawn = not notebook and os.environ.get("PYORERUN_HEADLESS", "0").lower() not in ("1", "true", "yes")
rr.init(f"{name}_{self.phase}", spawn=spawn)
rr.init(f"{name}_{self.phase}", spawn=spawn)
rr.log("/", rr.ViewCoordinates.RIGHT_HAND_Y_UP, static=True)
rr.send_blueprint(
rrb.Blueprint(
Expand Down
Loading