Skip to content
Merged
24 changes: 20 additions & 4 deletions scripts/reinforcement_learning/rsl_rl/export.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# scripts/reinforcement_learning/rsl_rl/export.py
#
# Export a trained rsl_rl policy as Kinfer binary.
#
# MODIFIED: This export script now accepts 16-dimensional command vectors from the deployment
# platform but only uses the first 3 dimensions (lin_vel_x, lin_vel_y, ang_vel_z) that the
# original model was trained on. The remaining 13 dimensions are ignored.
#
# Example usage: python scripts/reinforcement_learning/rsl_rl/export.py --task=Isaac-Velocity-Rough-Kbot-v0 --checkpoint ~/Github/IsaacLab/logs/rsl_rl/kbot_rough/[path_to_checkpoint].pt
# Or you can omit the checkpoint arg and it will use the latest checkpoint in the logs/rsl_rl/agent_name/ directory
import argparse
Expand Down Expand Up @@ -237,7 +242,12 @@ def main():
command_tensor = torch.cat([command_manager.get_command(name) for name in command_term_names], dim=-1)
command_tensor = command_tensor.to("cpu").flatten()

NUM_COMMANDS = command_tensor.shape[0]
# Original model expects 3D commands (lin_vel_x, lin_vel_y, ang_vel_z)
# But deployment platform provides 16D commands - we only use first 3
MODEL_NUM_COMMANDS = command_tensor.shape[0] # This is 3 for the original model
PLATFORM_NUM_COMMANDS = 16 # Platform provides 16D commands

print(f"[INFO] Model expects {MODEL_NUM_COMMANDS} command dimensions, but deployment platform provides {PLATFORM_NUM_COMMANDS} dimensions.")

def construct_obs_rnn(
projected_gravity: torch.Tensor,
Expand All @@ -247,12 +257,18 @@ def construct_obs_rnn(
gyroscope: torch.Tensor,
carry: torch.Tensor,
) -> torch.Tensor:
# Extract only the first 3 dimensions from the 16D command vector
# [0] x linear velocity [m/s]
# [1] y linear velocity [m/s]
# [2] z angular velocity [rad/s]
model_command = command[:MODEL_NUM_COMMANDS]

offset_joint_angles = joint_angles - _INIT_JOINT_POS
scaled_projected_gravity = projected_gravity / 9.81
obs = torch.cat(
(
scaled_projected_gravity,
command,
model_command,
offset_joint_angles,
joint_angular_velocities,
gyroscope,
Expand Down Expand Up @@ -301,7 +317,7 @@ def _init_fn() -> torch.Tensor:
torch.zeros(3),
torch.zeros(NUM_JOINTS),
torch.zeros(NUM_JOINTS),
torch.zeros(NUM_COMMANDS),
torch.zeros(PLATFORM_NUM_COMMANDS), # Use 16D command vector
torch.zeros(3),
torch.zeros(*CARRY_SHAPE),
)
Expand All @@ -312,7 +328,7 @@ def _init_fn() -> torch.Tensor:
joint_names = list(env.unwrapped.scene["robot"].data.joint_names)
metadata = PyModelMetadata(
joint_names=joint_names,
num_commands=NUM_COMMANDS,
num_commands=PLATFORM_NUM_COMMANDS, # Use 16D command vector size
carry_size=list(CARRY_SHAPE),
)

Expand Down
2 changes: 1 addition & 1 deletion source/isaaclab_assets/isaaclab_assets/robots/kscale.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,6 @@
joint_pos=_INIT_JOINT_POS,
joint_vel={".*": 0.0},
),
soft_joint_pos_limit_factor=0.9,
soft_joint_pos_limit_factor=1.0,
actuators=_ACTUATORS,
)
Original file line number Diff line number Diff line change
@@ -1 +1 @@
eb61befdd2f61e6071524a9a0e9dae4a
b01cba76b5e9249e61450f34aa6d792e
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@

# Instructions

For importing the kbot into Isaaclab


## URDF Importer

Instead of using the GUI option, use the script with command

```bash
# cd into Isaaclab folder
./isaaclab.sh -p scripts/tools/convert_urdf.py /path/to/robot.urdf /path/to/desired/output/robot.usd
```

The reason for this is that you need to NOT merge the joints, because otherwise the imu will get merged into the base and not have a "RigidBodyAPI" which is needed.

## Update training script

Note that you will need to change the names of anything referencing the geoms in the train config ,for example in:

`IsaacLab/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomotion/velocity/config/kbot/rough_rnn_env_cfg.py`

```python
# Physics material randomization (friction with the floor)
self.events.physics_material = EventTerm(
func=mdp.randomize_rigid_body_material,
mode="reset",
params={
"asset_cfg": SceneEntityCfg(
"robot", body_names=["LFootBushing_GPF_1517_12", "RFootBushing_GPF_1517_12"]
),
"static_friction_range": (0.1, 2.0),
"dynamic_friction_range": (0.1, 2.0),
"restitution_range": (0.0, 0.1),
"num_buckets": 64,
"make_consistent": True, # Ensure dynamic friction is always less than static friction
},
)

# Individual link mass randomization for robustness
self.events.add_limb_masses = EventTerm(
func=mdp.randomize_rigid_body_mass,
mode="reset",
params={
"asset_cfg": SceneEntityCfg(
"robot",
body_names=[
"KD_B_102B_TORSO_BTM",
"KD_D_102L_L_Hip_Yoke_Drive",
"KD_C_101L_ShldYokeDrive",
"KD_D_102R",
"KC_C_101R_ShldYokeDrive",
"L_Hip_Roll_RS03",
"L_Hip_Roll_RS03_2",
"RS03_4",
"RS03_3",
"KD_D_301L_L_Femur_Lower_Drive",
"KD_C_301L_LowerBicepDrive",
"KD_D_301R",
"KC_C_202R",
"KD_D_401L_L_Shin_Drive",
"KC_C_401L_Up_Forearm_Drive",
"KD_D_401R",
"KC_C_401R_R_UpForearmDrive",
"LFootBushing_GPF_1517_12",
"PRT0001_2",
"RFootBushing_GPF_1517_12",
"PRT0001",
],
),
"mass_distribution_params": (0.8, 1.2),
"operation": "scale",
"distribution": "uniform",
"recompute_inertia": True,
},
)
```


Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
asset_path: /home/ali/repos/ksim_stuff_new/make-assets/gen/kbot-headless-full-collisions/robot.urdf
usd_dir: /home/ali/repos/ksim_stuff_new/make-assets/gen/kbot-headless-full-collisions/w_imu
asset_path: /home/ali/repos/klab_stuff/kbot-headless/robot.urdf
usd_dir: /home/ali/repos/klab_stuff/kbot-headless/usd_out
usd_file_name: robot.usd
force_usd_conversion: true
make_instanceable: true
Expand All @@ -19,5 +19,5 @@ self_collision: false
replace_cylinders_with_capsules: false
collision_from_visuals: false
##
# Generated by UrdfConverter on 2025-07-22 at 14:22:48.
# Generated by UrdfConverter on 2025-09-09 at 19:00:07.
##
Git LFS file not shown
Git LFS file not shown
Git LFS file not shown
Git LFS file not shown
Loading
Loading