Skip to content

Lorenzo manipulation floor release - #97

Open
LBarbieri24 wants to merge 106 commits into
mainfrom
lorenzo_manipulation_floor_release
Open

Lorenzo manipulation floor release#97
LBarbieri24 wants to merge 106 commits into
mainfrom
lorenzo_manipulation_floor_release

Conversation

@LBarbieri24

Copy link
Copy Markdown

No description provided.

@LBarbieri24
LBarbieri24 force-pushed the lorenzo_manipulation_floor_release branch from e46c436 to cd81d16 Compare July 20, 2026 09:57
Comment thread .python-version Outdated
@@ -1 +1 @@
3.13
3.11

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change it back to 13 or 14

Comment thread pyproject.toml Outdated
"mjlab>=1.5.2",
"moviepy>=2.0"
"moviepy>=2.0",
"onnxruntime<1.24",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explain why this change

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what was the problem back at the beginning but now after removing "onnxruntime<1.24" it doesn't seem to appear an error anymore.

Comment thread scripts/collect_rewards.py Outdated
Comment on lines +401 to +422
output_blocks.append(display_curriculum(task, curriculum, args.format))

terminations = collect_terminations(task, play=args.play)
if terminations is not None:
output_blocks.append(display_terminations(task, terminations, args.format))

noise = collect_noise(task, play=args.play)
if noise is not None:
output_blocks.append(display_noise(task, noise, args.format))

full_output = "\n".join(output_blocks)

if args.output:
with open(args.output, "w") as f:
f.write(full_output)
print(f"Results successfully written to {args.output}")
else:
print(full_output)


if __name__ == "__main__":
main()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this script?

@LBarbieri24 LBarbieri24 Jul 23, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't actually. These were all utility scripts used mainly for debugging. I have removed them

Comment thread scripts/evaluate_policy.py Outdated
Comment on lines +1 to +10
#!/usr/bin/env python3
"""
Script to evaluate a trained policy on 100 episodes and record key metrics:
- success rate
- number of episodes with top surface collisions
- mean fingertip angles wrt cube lateral surfaces the instant before contact_both_fingers

Supports both ground truth state feedback and a hybrid YOLO-based estimation mode.
"""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this script too?

Comment thread scripts/export_onnx.py Outdated
Comment on lines +28 to +52
def main():
parser = argparse.ArgumentParser(
description="Export a .pt checkpoint to .onnx with metadata"
)
parser.add_argument(
"--task",
type=str,
required=True,
help="Task name (e.g., Mjlab-Manipulation-Lift-Cube-Pal-Tiago-Pro-v0)",
)
parser.add_argument(
"--checkpoint", type=str, required=True, help="Path to the .pt checkpoint file"
)
parser.add_argument(
"--output",
type=str,
default=None,
help="Optional custom output path for the .onnx file (defaults to same folder/name as checkpoint)",
)
parser.add_argument(
"--device",
type=str,
default="cpu",
help="Device to load the model on (default: cpu)",
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you have to do it with a script?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used it to convert middle .pt checkpoints into .onnx

Comment thread scripts/play_and_print.py Outdated
Comment on lines +1 to +20
import argparse
import math
import os
import sys

import cv2
import mjlab.tasks # noqa: F401
import numpy as np
import torch
from mjlab.envs import ManagerBasedRlEnv
from mjlab.rl import RslRlVecEnvWrapper
from mjlab.sensor import CameraSensorCfg
from mjlab.tasks.registry import load_env_cfg, load_rl_cfg
from mjlab.utils.lab_api.math import euler_xyz_from_quat, quat_apply, quat_inv
from mjlab.utils.torch import configure_torch_backends
from mjlab.viewer import NativeMujocoViewer, ViserPlayViewer

# Sourcing the filters from the workspace
sys.path.append("/home/lorenzobarbieri/exchange/tiago_pro_sim_ws/src")
try:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

<!-- <camera name="head_realsense_camera" pos="0.0565 -0.168 0" euler="0 -1.57 0" fovy="60"/> -->
</body>
</body>
<!--

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WHy the whole block is commented?

Comment on lines +10 to +36
class TiagoProRobot:
entity_cfg: EntityCfg = field(default_factory=get_tiago_pro_robot_cfg)
arm_joint_pattern: str = "arm_right_.*_joint"
gripper_joint_pattern: str = "gripper_right_finger_joint"
ee_site: str = "gripper_right_grasping_site"
fingertip_geom_pattern: str = "col_right_fingertip_.*"
fingertip_site_pattern: str = "gripper_right_fingertip_.*_site"
collision_link_pattern: str = "(arm_right|gripper_right)_.*_link"
arm_collision_link_pattern: str = "arm_right_.*_link"
gripper_collision_link_pattern: str = "gripper_right_.*_link"
viewer_body: str = "base_footprint"
camera_name: str = "head_realsense_camera"
wrist_camera_name: str = "wrist_realsense_camera"
head_camera_name: str = "head_realsense_camera"

def arm_action_cfg(self) -> Any:
from mjlab.envs.mdp.actions import DifferentialIKActionCfg

return DifferentialIKActionCfg(
entity_name="robot",
actuator_names=(self.arm_joint_pattern,),
frame_name=self.ee_site,
frame_type="site",
delta_pos_scale=0.005, # Max displacement of 0.01m per step (0.5m/s max velocity)
delta_ori_scale=0.005, # Max rotation of 0.01 rad per step (0.5 rad/s max angular velocity)
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What this file used for?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I incorporated it in tiago_pro_constants.py now.

@LBarbieri24
LBarbieri24 marked this pull request as ready for review July 30, 2026 10:02
Copilot AI review requested due to automatic review settings July 30, 2026 10:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a PAL TIAGo Pro manipulation “lift cube” RL task to the pal_mjlab task suite, including environment/MDP definitions, PPO runner configuration, and robot model/actuation updates to support the new setup.

Changes:

  • Introduces a new TIAGo Pro lift-cube task package (env cfg, PPO cfg, task registration) plus a manipulation MDP module (commands/obs/rewards/events/terminations/metrics).
  • Updates the TIAGo Pro MuJoCo XML and robot constants (actuators, collisions, initial state, camera) to match the manipulation setup.
  • Adds runner/export monkey patches (metadata + ONNX loading) and updates project dependencies / ignore rules.

Reviewed changes

Copilot reviewed 19 out of 22 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/pal_mjlab/tasks/manipulation/tiago_pro/rl_cfg.py Adds PPO runner/model hyperparameter config for the lift task.
src/pal_mjlab/tasks/manipulation/tiago_pro/env_cfgs.py Defines the TIAGo Pro lift environment (scene/actions/obs/rewards/DR/terminations).
src/pal_mjlab/tasks/manipulation/tiago_pro/init.py Registers the TIAGo Pro lift task in the mjlab task registry.
src/pal_mjlab/tasks/manipulation/README.md Documents the manipulation task layout and tuning notes.
src/pal_mjlab/tasks/manipulation/mdp/utils.py Adds nan_safe helper for reward sanitization.
src/pal_mjlab/tasks/manipulation/mdp/terminations.py Adds manipulation termination terms (success/failure + penetration).
src/pal_mjlab/tasks/manipulation/mdp/rewards.py Adds shaped reward/penalty terms for reaching/grasping/lifting/releasing.
src/pal_mjlab/tasks/manipulation/mdp/observations.py Adds manipulation observation terms (object pose, EE pose, contact flags).
src/pal_mjlab/tasks/manipulation/mdp/metrics.py Adds metrics terms for logging success, errors, and distances.
src/pal_mjlab/tasks/manipulation/mdp/events.py Adds reset logic and DR utilities (e.g., table height randomization).
src/pal_mjlab/tasks/manipulation/mdp/curriculums.py Adds a placeholder curriculum module.
src/pal_mjlab/tasks/manipulation/mdp/contact_sensor.py Adds fingertip proximity/contact helper used by obs/rewards/terms.
src/pal_mjlab/tasks/manipulation/mdp/commands.py Implements the lifting command term and procedural table/box specs.
src/pal_mjlab/tasks/manipulation/mdp/init.py Re-exports manipulation MDP submodules.
src/pal_mjlab/tasks/manipulation/init.py Introduces the manipulation task package entrypoint.
src/pal_mjlab/tasks/init.py Adds monkey patches for exporter metadata and ONNX inference loading.
src/pal_mjlab/robots/pal_tiago_pro/xmls/tiago_pro.xml Updates TIAGo Pro XML (gripper structure, collisions, camera, etc.).
src/pal_mjlab/robots/pal_tiago_pro/tiago_pro_constants.py Updates TIAGo Pro actuator/collision setup and exports a TiagoProRobot helper.
src/pal_mjlab/robots/init.py Exposes TiagoProRobot from the robots package.
pyproject.toml Adds dependencies and configures uv sources/indexes for torch wheels.
.gitignore Ignores additional artifacts (datasets, zips, results, scripts).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +164 to +170
def task_success_reward(
env: ManagerBasedRlEnv,
command_name: str,
floor_z: float = 0.1,
) -> torch.Tensor:
"""Returns 1.0 if the object has reached the target and fallen to the floor, else 0.0."""
return object_released_on_floor_term(env, command_name, floor_z).float()
Comment on lines +58 to +80
def get_top_penetration_depth(p_local: torch.Tensor) -> torch.Tensor:
x = p_local[:, 0]
y = p_local[:, 1]
z = p_local[:, 2]

is_inside = (
(torch.abs(x) <= half_x) & (torch.abs(y) <= half_y) & (torch.abs(z) <= half_z)
)

# Distances to each face
dist_x = half_x - torch.abs(x)
dist_y = half_y - torch.abs(y)
dist_z = half_z - torch.abs(z)

dists = torch.stack([dist_x, dist_y, dist_z], dim=-1)
min_dist, min_axis = torch.min(dists, dim=-1)

# Condition: inside, closest to top face (min_axis == 2) and in upper half (z > 0)
is_top_penetration = is_inside & (min_axis == 2) & (z > 0)

# Return penetration depth if top penetration, else 0.0
return torch.where(is_top_penetration, min_dist, torch.zeros_like(min_dist))

Comment on lines +19 to +20
joint_action = env.action_manager.get_term("joint_pos")
assert isinstance(joint_action, BaseAction)
Comment thread pyproject.toml
Comment on lines +44 to +55
[[tool.uv.index]]
name = "pytorch-cu129"
url = "https://download.pytorch.org/whl/cu129"
explicit = true

[tool.uv.sources]
torch = [
{ index = "pytorch-cu129", marker = "extra == 'cu128' and sys_platform == 'linux'" }
]
torchvision = [
{ index = "pytorch-cu129", marker = "extra == 'cu128' and sys_platform == 'linux'" }
]
Comment on lines +35 to +47
#### Core Task Registration & Configs (`tiago_pro/`)
- [`tiago_pro/__init__.py`](file:///home/lorenzobarbieri/pal_mjlab_manipulation/pal_mjlab/src/pal_mjlab/tasks/manipulation/tiago_pro/__init__.py): Registers `Mjlab-Manipulation-Lift-Cube-Pal-Tiago-Pro-v0` into the `mjlab` task registry using `ManipulationOnPolicyRunner`.
- [`tiago_pro/env_cfgs.py`](file:///home/lorenzobarbieri/pal_mjlab_manipulation/pal_mjlab/src/pal_mjlab/tasks/manipulation/tiago_pro/env_cfgs.py): Defines `lift_env_cfg()`, configuring simulation parameters ($dt = 0.005\text{ s}$, decimation = 4 $\rightarrow 50\text{ Hz}$ control rate, 4s episodes), scene entities (robot, table, box), sensor suite, asymmetric actor/critic observations, reward terms, domain randomizations, and terminations.
- [`tiago_pro/rl_cfg.py`](file:///home/lorenzobarbieri/pal_mjlab_manipulation/pal_mjlab/src/pal_mjlab/tasks/manipulation/tiago_pro/rl_cfg.py): Defines `lift_ppo_runner_cfg()`, providing hyperparameter settings for PPO training via RSL-RL (Actor/Critic MLPs: `512 x 256 x 128`, ELU activations, adaptive LR schedule).

#### MDP Infrastructure (`mdp/`)
- [`mdp/commands.py`](file:///home/lorenzobarbieri/pal_mjlab_manipulation/pal_mjlab/src/pal_mjlab/tasks/manipulation/mdp/commands.py): Implements `LiftingCommand` and `LiftingCommandCfg`. Generates random box spawn poses and target goal 3D positions in space, procedural MuJoCo XML specs for table (`get_table_spec`) and box (`get_box_spec`), and manages episode metrics (`reached`, `at_goal_time`, `grasped_distance`).
- [`mdp/contact_sensor.py`](file:///home/lorenzobarbieri/pal_mjlab_manipulation/pal_mjlab/src/pal_mjlab/tasks/manipulation/mdp/contact_sensor.py): Provides `site_contact_both_fingers()`, which checks proximity and contact between both right fingertips and the target object.
- [`mdp/events.py`](file:///home/lorenzobarbieri/pal_mjlab_manipulation/pal_mjlab/src/pal_mjlab/tasks/manipulation/mdp/events.py): Contains custom domain randomization terms including `randomize_table_height` (shifts table top while keeping it grounded) and `reset_joints_mixed` (initializes arm joints near default or goal configurations).
- [`mdp/observations.py`](file:///home/lorenzobarbieri/pal_mjlab_manipulation/pal_mjlab/src/pal_mjlab/tasks/manipulation/mdp/observations.py): Features spatial observation calculators relative to the robot root frame (`object_position_in_robot_root_frame`, `object_yaw_in_robot_root_frame`, `ee_position_in_robot_base_frame`, `reached_flag`, `object_both__contact_fingers`).
- [`mdp/rewards.py`](file:///home/lorenzobarbieri/pal_mjlab_manipulation/pal_mjlab/src/pal_mjlab/tasks/manipulation/mdp/rewards.py): Collection of shaped reward terms (`reaching_object`, `gripper_open_during_approach`, `lifting_object`, `object_goal_tracking`, `post_reached_ee_stability`, `post_reached_gripper_open`) and penalty terms (`top_surface_penetration_penalty`, `object_table_sliding_penalty`, `fingertip_cube_alignment_reward_adaptive`, `arm_right_1_joint_limit_penalty`, `self_collisions`).
- [`mdp/terminations.py`](file:///home/lorenzobarbieri/pal_mjlab_manipulation/pal_mjlab/src/pal_mjlab/tasks/manipulation/mdp/terminations.py): Defines episode termination conditions (`object_released_on_floor_term`, `cube_contact_with_table_after_reached_term`, `cube_fell_off_table_term`, `top_surface_penetration_term`, `nan_term`).
- [`mdp/utils.py`](file:///home/lorenzobarbieri/pal_mjlab_manipulation/pal_mjlab/src/pal_mjlab/tasks/manipulation/mdp/utils.py): Provides `@nan_safe` wrapper decorator to sanitize potential NaNs/Infs in reward outputs.
# - Base: col_base
# - Torso/Head:col_torso_head
# - Right arm joints 3, 5, 7: col_upper_right_arm, col_lower_right_arm, col_arm_right_7
# (right arm joint 1 has no collision geom in the XML)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants