Skip to content

Conversation

@grzemal
Copy link

@grzemal grzemal commented Oct 18, 2025

Description

This PR introduces multirotor and thruster support and adds a manager-based example/task for the LMF2 drone. The change contains a new low-level thruster actuator model, a new Multirotor articulation asset class + configs, new thrust actions, and a manager-based drone task (LMF2) with MDP configs and RL agent configs.

Motivation and context

  • Provides a reusable multirotor abstraction and a parameterized thruster actuator model so we can simulate multirotor vehicles (quad/hex/other).
  • Adds a manager-based LMF2 drone task and configuration files to enable repro and training workflows for the LMF2 platform.
  • Consolidates drone-specific code and prepares the repo for future control/sensor improvements.

Type of change

  • New feature (non-breaking addition of new functionality)
  • Documentation update (added docs/comments where applicable)

Files changed (high-level summary)

  • New/major files added:
    • source/isaaclab/isaaclab/actuators/thruster.py (new thruster actuator model)
    • source/isaaclab/isaaclab/assets/articulation/multirotor.py (new multirotor articulation)
    • source/isaaclab/isaaclab/assets/articulation/multirotor_cfg.py
    • source/isaaclab/isaaclab/assets/articulation/multirotor_data.py
    • source/isaaclab/isaaclab/envs/mdp/actions/thrust_actions.py
    • source/isaaclab_assets/isaaclab_assets/robots/lmf2.py and LMF2 URDF + asset files (lmf2.urdf, lmf2.zip, .asset_hash)
    • source/isaaclab_tasks/isaaclab_tasks/manager_based/drone_ntnu/* (new task code, commands, observations, rewards, state-based control configs and agent configs)
  • Modified:
    • source/isaaclab/isaaclab/actuators/actuator_cfg.py (register thruster config)
    • source/isaaclab/isaaclab/envs/mdp/actions/actions_cfg.py (register thrust actions)
    • small edits to various utils and types, and docs/make.bat
  • Total diff (branch vs main when I checked): 33 files changed, ~2225 insertions, 65 deletions

Dependencies

  • No new external top-level dependencies introduced. The branch adds assets (binary .zip) — ensure Git LFS is used if you want large assets tracked by LFS.
  • The new drone task references standard repo-internal packages and Isaac Sim; no external pip packages required beyond the repo standard.

Checklist (status)

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the changelog and the corresponding version in the extension's config/extension.toml file
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

@github-actions github-actions bot added documentation Improvements or additions to documentation enhancement New feature or request asset New asset feature or request labels Oct 18, 2025
@Mayankm96 Mayankm96 moved this to Ready in Isaac Lab Oct 20, 2025
Copy link
Collaborator

@pascal-roth pascal-roth left a comment

Choose a reason for hiding this comment

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

Thanks for getting the PR up, looks already great!

Here some comments regarding but have to do a deep dive when I have more time

Copy link
Collaborator

Choose a reason for hiding this comment

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

What changed in this file that all lines are deleted and readded? They appear to be the same for me

Copy link
Author

Choose a reason for hiding this comment

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

as well it was not clear to me, but maybe this change fixes that issue: fc2ff6c

Comment on lines 295 to 296
# stiffness = 0.1 # only necessary to make this conform with Isaac
# damping = 0.1 # only necessary to make this conform with Isaac
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can be removed?

Copy link
Author

Choose a reason for hiding this comment

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

addressed in 3292b8d

# stiffness = 0.1 # only necessary to make this conform with Isaac
# damping = 0.1 # only necessary to make this conform with Isaac

dt: float = 0.01
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should probably be relative to the step time of PhysX timesteps (otherwise can intrigue infeasible cases where Physx timestamp > dt)

Copy link
Author

@grzemal grzemal Oct 22, 2025

Choose a reason for hiding this comment

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

yes, changed to set this parameter based on the sim.dt: cdb9380

Comment on lines +301 to +302
num_motors: int = 4
"""Number of motors/propulsors on the vehicle."""
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't that not be readable from the urdf? Similar to joints?

Comment on lines +310 to +311
thrust_const_range: tuple[float, float] = (9.26312e-06, 1.826312e-05)
"""Range for thrust coefficient :math:`k_f` when ``use_rps=True`` [N/(rps²)]."""
Copy link
Collaborator

Choose a reason for hiding this comment

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

Question: where are all of these default values coming from? They seem to be very specific while the general Thruster class should be generic

Copy link
Author

Choose a reason for hiding this comment

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

yes, they are platform/hardware depended (so in this case LMF2 specific). we will moved them where we load the LMF2 robot model and keep the thruster as generic as possible

if env_ids is None:
env_ids = torch.arange(self.num_instances, device=self.device)
else:
env_ids = torch.tensor(env_ids, device=self.device)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Careful, enc ids are often a tensor already

Copy link
Author

Choose a reason for hiding this comment

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

addressed in a717121


# reset multirotor-specific data
if env_ids is None:
env_ids = torch.arange(self.num_instances, device=self.device)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should generate an attr ALL_INDICIES to avoid reallocating memory here often

Copy link
Author

Choose a reason for hiding this comment

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

addressed in a717121


@torch.jit.script
def rand_range(lower, upper):
# type: (torch.Tensor, torch.Tensor) -> torch.Tensor
Copy link
Collaborator

Choose a reason for hiding this comment

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

Type annotation in the function call or why is it defined as comment here?

Copy link
Author

@grzemal grzemal Oct 23, 2025

Choose a reason for hiding this comment

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

function removed, switched to the isaac lab math_utils.sample_uniform
b6d30f0

Copy link
Collaborator

Choose a reason for hiding this comment

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

We should not add a zip file to the git. Let's find a differ location if the data is crucial

Copy link
Collaborator

@ooctipus ooctipus left a comment

Choose a reason for hiding this comment

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

made some high level pass through,

Thanks for working on this PR! my high level comment so far would be try to use more IsaacLab predefined mdp if you find it has large overlap with custom mdp.

from .commands_cfg import DroneUniformPoseCommandCfg


class DroneUniformPoseCommand(CommandTerm):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we use the UniformPoseCommand directly from IsaacLab?

Copy link
Author

@grzemal grzemal Oct 23, 2025

Choose a reason for hiding this comment

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

so this class does not change much from the original UniformPoseCommand, but it introduces changes that help to

  • visualize the goal coordinate frame in the current sub-terrain: lines 153 - 155
  • compute the position error in the current subterrain: line 103

These changes are especially required by drone navigation task.

# extract euler angles (in world frame)
roll, pitch, _ = math_utils.euler_xyz_from_quat(asset.data.root_quat_w)
# normalize angle to [-pi, pi]
roll = torch.atan2(torch.sin(roll), torch.cos(roll))
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we have warp_to_pi from math_utils

Copy link
Author

@grzemal grzemal Oct 23, 2025

Choose a reason for hiding this comment

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

yes, I didn't notice it, since the humanoid example uses also such implementation,
comment addressed in 476798d

"""
Drone-navigation rewards.
"""

Copy link
Collaborator

Choose a reason for hiding this comment

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

It is ok to define custom reward here , though I will highly suggest if you can find some predefined IsaacLab reward mdp.

For example, flat_orientation_l2 could be an good alternative to upright_posture_reward, have a read to source/isaaclab/isaaclab/envs/mdp/rewards.py

Copy link
Author

Choose a reason for hiding this comment

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

yes, you're right. Some modifications addressed in 9d59216. For the velocity (linear and angular) terms, the predefined IsaacLab reward mdp does not have terms for XYZ velocities together so I added these functions (following similar naming convention) in our custom reward in 9d59216

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

asset New asset feature or request documentation Improvements or additions to documentation enhancement New feature or request

Projects

Status: Ready

Development

Successfully merging this pull request may close these issues.

6 participants