-
Notifications
You must be signed in to change notification settings - Fork 5
Add factory_assembly_task and the relevant task examples #285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| @register_asset | ||
| class SmallGear(FactoryObject): | ||
| """ | ||
| A small reference gear for gear mesh task. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, this could be used by other tasks as well not just for "gear mesh task"? Suggest to update the comment
|
|
||
|
|
||
| @register_asset | ||
| class FactoryTableBackground(LibraryBackground): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets maybe call this the SeattleLabTable :)
| def __init__(self, prim_path: str | None = None, initial_pose: Pose | None = None): | ||
| super().__init__(prim_path=prim_path, initial_pose=initial_pose) | ||
|
|
||
| # Create factory-specific articulation configuration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that this is being done so one can set other properties to the articulation. I think we should fix this directly where we generally create the articulations so we dont have extra functions.
| from isaaclab_arena.terms.events import set_object_pose | ||
| from isaaclab_arena.utils.cameras import get_viewer_cfg_look_at_object | ||
|
|
||
| FRANKA_PANDA_FACTORY_HIGH_PD_CFG = FRANKA_PANDA_HIGH_PD_CFG.copy() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think it would be nice to have this as a function ? Maybe we will also use this for other tasks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @viiik-inside, what do you mean by “having this as a function”? Do you mean wrapping all of this into a standalone function?
This is a reference implementation of franka.py in Isaac Lab. I've put these configs in franka.py of Arena embodiments. I'd like to know your suggestions on this.
from isaaclab_assets.robots.franka import FRANKA_PANDA_HIGH_PD_CFG
FRANKA_PANDA_FACTORY_HIGH_PD_CFG = FRANKA_PANDA_HIGH_PD_CFG.copy()
FRANKA_PANDA_FACTORY_HIGH_PD_CFG.spawn.activate_contact_sensors = True
FRANKA_PANDA_FACTORY_HIGH_PD_CFG.spawn.rigid_props.disable_gravity = True
FRANKA_PANDA_FACTORY_HIGH_PD_CFG.actuators["panda_shoulder"].stiffness = 150.0
FRANKA_PANDA_FACTORY_HIGH_PD_CFG.actuators["panda_shoulder"].damping = 30.0
FRANKA_PANDA_FACTORY_HIGH_PD_CFG.actuators["panda_forearm"].stiffness = 150.0
FRANKA_PANDA_FACTORY_HIGH_PD_CFG.actuators["panda_forearm"].damping = 30.0
FRANKA_PANDA_FACTORY_HIGH_PD_CFG.actuators["panda_hand"].stiffness = 150.0
FRANKA_PANDA_FACTORY_HIGH_PD_CFG.actuators["panda_hand"].damping = 30.0
FRANKA_PANDA_FACTORY_HIGH_PD_CFG.init_state.pos = (0.0, 0.0, 0.0) # for factory assembly task``` | self.held_asset = held_asset | ||
| self.assist_asset_list = assist_asset_list | ||
| self.background_scene = background_scene | ||
| self.scene_config = InteractiveSceneCfg(num_envs=1, env_spacing=3.0, replicate_physics=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this here? If yes, maybe lets make them parameters
| params={ | ||
| "object_cfg": SceneEntityCfg(self.held_asset.name), | ||
| "target_object_cfg": SceneEntityCfg(self.fixed_asset.name), | ||
| "max_x_separation": 0.020, # Tolerance for assembly alignment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to have these as parameters. Maybe a dataclass ?
|
|
||
| """This sub-module contains the functions that are specific to the environment.""" | ||
|
|
||
| from isaaclab.envs.mdp import * # noqa: F401, F403 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason why this folder is called mdp? Just curious
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is following the convention used in IsaacLab mdp. The events, observations, and terminations for the task example are placed in the mdp folder.
| func=randomize_object_serials_pose, | ||
| mode="reset", | ||
| params={ | ||
| "pose_range": {"x": (0.25, 0.6), "y": (-0.20, 0.20), "z": (0.0, 0.0), "yaw": (-1.0, 1.0)}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use our pose dataclass here
| from isaaclab_arena_environments.mdp.events import randomize_object_serials_pose | ||
|
|
||
| @configclass | ||
| class EventCfgGearMesh: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be in the task class?
| from isaaclab_arena_environments import mdp | ||
|
|
||
| @configclass | ||
| class EventCfgPegInsert: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it has to be here, then we can add it outside this function, on top of the file maybe?
alexmillane
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Thank you for doing this!
We have requested a few changes.
One additional request is that we add a test for the FactoryAssemblyTask. Such a such could just start the task, then teleport objects into a success configuration and then check that things succeed.
| object_min_z = -0.1 | ||
|
|
||
| def __init__(self): | ||
| super().__init__(scale=(1.0, 1.0, 1.0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we passing the scale of 1.0 here? I would have thought that the default scale is 1.0? Can we remove this?
| def create_factory_articulation_cfg( | ||
| prim_path: str, | ||
| usd_path: str, | ||
| scale: tuple[float, float, float], | ||
| mass: float, | ||
| rigid_props: sim_utils.RigidBodyPropertiesCfg = RIGID_BODY_PROPS_HIGH_PRECISION, | ||
| contact_offset: float = 0.005, | ||
| rest_offset: float = 0.0, | ||
| ) -> ArticulationCfg: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To echo what @viiik-inside said above, we need to expose this functionality through our Object class. I would suggest that we make a proposal next week, formulated as an MR against this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modify the code based on the new MR.
| if ( | ||
| i == 0 | ||
| ): # set the "small_gear" and "large_gear" positions according the position of fixed_asset('gear_base') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to make some assumptions about the order of the assets in the list. Is that correct? I would guess that it makes the assumption that the "fixed_asset" appears first in the list. Could we enforce this assumption using the function parameters? For example we could do something like:
def randomize_object_serials_pose(
env: ManagerBasedEnv,
env_ids: torch.Tensor,
fixed_asset_cfg: SceneEntityCfg,
asset_cfgs: list[SceneEntityCfg],
min_separation: float = 0.0,
pose_range: dict[str, tuple[float, float]] = {},
max_sample_tries: int = 5000,
relative_asset_cfgs: SceneEntityCfg | None = None,
):
Such that the fixed_asset is passed separately. That way we remove assumptions about the order of assets in the list.
| asset_cfg = asset_cfgs[i] | ||
| asset = env.scene[asset_cfg.name] | ||
|
|
||
| # Write pose to simulation | ||
| pose_tensor = torch.tensor([pose_list[i]], device=env.device) | ||
| positions = pose_tensor[:, 0:3] + env.scene.env_origins[cur_env, 0:3] | ||
| orientations = math_utils.quat_from_euler_xyz(pose_tensor[:, 3], pose_tensor[:, 4], pose_tensor[:, 5]) | ||
|
|
||
| asset.write_root_pose_to_sim( | ||
| torch.cat([positions, orientations], dim=-1), env_ids=torch.tensor([cur_env], device=env.device) | ||
| ) | ||
| asset.write_root_velocity_to_sim( | ||
| torch.zeros(1, 6, device=env.device), env_ids=torch.tensor([cur_env], device=env.device) | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code to get an asset and set it's pose and velocity as zero is repeated in this file. Here and below.
Suggestion to move it out to another function in this same file. Something like:
def set_pose_and_zero_velocity(env, asset_cfg, positions, orientations):
This will make this function more easily understood.
| def randomize_object_serials_pose( | ||
| env: ManagerBasedEnv, | ||
| env_ids: torch.Tensor, | ||
| asset_cfgs: list[SceneEntityCfg], | ||
| min_separation: float = 0.0, | ||
| pose_range: dict[str, tuple[float, float]] = {}, | ||
| max_sample_tries: int = 5000, | ||
| relative_asset_cfgs: SceneEntityCfg | None = None, | ||
| ): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion to rename this function to something that indicates what it does. It's more specific than just randomizing poses. It randomizes poses, and then does something special with the relative assets.
Perhaps a docstring would help?
| task = FactoryAssemblyTask( | ||
| fixed_asset=gear_base, | ||
| held_asset=medium_gear, | ||
| assist_asset_list=[small_gear, large_gear], | ||
| background_scene=background, | ||
| ) | ||
| task.events_cfg = EventCfgGearMesh() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We replace the event_cfg in the underlying task. Do we ever use the original event_cfg defined in FactoryAssemblyTask?
| FRANKA_PANDA_FACTORY_HIGH_PD_CFG.init_state.pos = (0.0, 0.0, 0.0) # for factory assembly task | ||
|
|
||
|
|
||
| class FactoryAssemblyTask(TaskBase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FactoryAssemblyTask -> AssemblyTask
There's nothing specific to factories here.
| """ | ||
| Factory assembly task where an object needs to be assembled with a base object, like peg insert, gear mesh, etc. | ||
| """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion to expand this docstring. From what I can tell, the goal in this task is to bring two objects into proximity. There are some additional (distractor?) objects in the scene (which are not involved in the task but are there to make things harder?).
If possible, could you expand the docstring to make that clear?
| randomize_gear_positions = EventTerm( | ||
| func=randomize_object_serials_pose, | ||
| mode="reset", | ||
| params={ | ||
| "pose_range": {"x": (0.25, 0.6), "y": (-0.20, 0.20), "z": (0.0, 0.0), "yaw": (-1.0, 1.0)}, | ||
| "min_separation": 0.18, | ||
| "asset_cfgs": [SceneEntityCfg("gear_base"), SceneEntityCfg("medium_gear")], | ||
| "relative_asset_cfgs": [SceneEntityCfg("small_gear"), SceneEntityCfg("large_gear")], | ||
| }, | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we think of a way of incorperating this EventCfg in the FactoryAssemblyTask.
For example, the FactoryAssemblyTask could take an additional parameter randomization_mode where we select among a few different options for randomizing the assets.
What do you think? Is that possible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion, thanks. I’ve updated the code accordingly.
| randomize_peg_hole_positions = EventTerm( | ||
| func=randomize_object_pose, | ||
| mode="reset", | ||
| params={ | ||
| "pose_range": { | ||
| "x": (0.2, 0.6), | ||
| "y": (-0.20, 0.20), | ||
| "z": (0.0, 0.0), | ||
| "yaw": (-1.0, 1.0), | ||
| }, | ||
| "min_separation": 0.1, | ||
| "asset_cfgs": [SceneEntityCfg("peg"), SceneEntityCfg("hole")], | ||
| }, | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as my comment above: what do you think about incorperating this into FactoryAssemblyTask with an option for reset mode.
82ae523 to
87a2ac6
Compare
- Generalize FactoryAssemblyTask to AssemblyTask for generic base-object assembly - Centralize EventsCfg in the atomic task with randomization_mode for asset randomization variants - Simplify assembly asset initialization via spawn_cfg_addon and asset_cfg_addon - Add test script for the assembly task - Add docstrings for relevant functions - Use parameters instead of hard-coded values for flexibility
- Generalize FactoryAssemblyTask to AssemblyTask for generic base-object assembly - Centralize EventsCfg in the atomic task with randomization_mode for asset randomization variants - Simplify assembly asset initialization via spawn_cfg_addon and asset_cfg_addon - Add test script for the assembly task - Add docstrings for relevant functions - Use parameters instead of hard-coded values for flexibility
|
Hi @alexmillane @viiik-inside @cvolkcvolk, thanks for your review and suggestions.
I won’t reply to every comment individually to keep the thread concise, but I’ve gone through all of your suggestions and applied the corresponding changes. Could you please take another look? |
Summary
Add a generic
assembly_task(bring two objects into proximity) and corresponding task examples: peg insertion and gear meshing.Detailed description
peg_insertandgear_meshexamples are added to demonstrate how to use this atomic task in practice.assembly_task, plus a test script for this task.peg_insertandgear_mesh.Open issues
For the
peg_inserttask, the current peg and hole assets are not compatible with Pinocchio. Ideally, this configuration should be defined at the task environment level so that everyone uses the correct setup by default. However, an effective solution has not been found yet, so this is left to Vikram Ramasamy for follow-up (see the discussion on slack ).Verification
Dataset Preparation
Please dowload the pre-recorded hdf5 files from link and place them in the
datasetsfolder.Test Commands
Peg insertion task example
Since AVP teleop support is not available for Franka, I used an old HDF5 dataset with AbsEEF + binary gripper. Before running
replay_demos.py, please updatefranka.pyas follows, then you can use the original HDF5 dataset for demonstration replay.use_relative_modefrom True to False.scalefrom 0.5 to 1.Gear meshing task example
For the same reason as above, please update the
arm_actioninfranka.pyaccordingly.