Skip to content

Add implementation of mjd_ellipsoidFluid derivative#897

Open
Aaryan-549 wants to merge 5 commits into
google-deepmind:mainfrom
Aaryan-549:feature/add-mjd-ellipsoidfluid-implementation
Open

Add implementation of mjd_ellipsoidFluid derivative#897
Aaryan-549 wants to merge 5 commits into
google-deepmind:mainfrom
Aaryan-549:feature/add-mjd-ellipsoidfluid-implementation

Conversation

@Aaryan-549
Copy link
Copy Markdown
Contributor

Fixes #750
Implements derivative of ellipsoid-based fluid forces with respect to velocities. Includes all component derivatives:

  • Added mass forces
  • Viscous torque and drag
  • Kutta lift
  • Magnus force

The implementation adds the fluid force derivatives to qDeriv, following the pattern from the reference C implementation.

@thowell thowell self-requested a review December 11, 2025 16:29
Comment thread mujoco_warp/_src/derivative.py
Comment thread mujoco_warp/_src/derivative.py
Comment thread mujoco_warp/_src/derivative.py Outdated
Comment thread mujoco_warp/_src/derivative.py Outdated
slender_drag_coef = geom_fluid[geomid, 2]
ang_drag_coef = geom_fluid[geomid, 3]

if density > 0.0 and magnus_coef != 0.0:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lets structure this with one if density > 0.0 check and checks for magnus_coef, kutta_coef and viscosity in the density check scope.

Comment thread mujoco_warp/_src/derivative.py Outdated


@wp.func
def _pow2_deriv(val: float) -> float:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this function is unused, lets remove it

Comment thread mujoco_warp/_src/derivative.py Outdated
lin_vel = wp.spatial_bottom(local_vels)
ang_vel = wp.spatial_top(local_vels)

virtual_lin_mom = wp.vec3(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

fluid_density * wp.cw_mul(virtual_mass, lin_vel)

Comment thread mujoco_warp/_src/derivative.py Outdated
fluid_density * virtual_mass[1] * lin_vel[1],
fluid_density * virtual_mass[2] * lin_vel[2]
)
virtual_ang_mom = wp.vec3(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

fluid_density * wp.cw_mul(virtual_inertia, ang_vel)

Comment thread mujoco_warp/_src/derivative.py Outdated
ang_drag_coef * II[2] + slender_drag_coef * (I_max - II[2])
)

mom_visc = wp.vec3(x * mom_coef[0], y * mom_coef[1], z * mom_coef[2])
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

wp.cw_mul(ang, mom_coef)

Comment thread mujoco_warp/_src/derivative.py Outdated

mom_visc = wp.vec3(x * mom_coef[0], y * mom_coef[1], z * mom_coef[2])
norm = wp.length(mom_visc)
density = fluid_density / wp.max(wp.static(1e-10), norm)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lets utilize MJ_MINVAL instead of wp.static(1e-10)

Comment thread mujoco_warp/_src/derivative.py Outdated
norm = wp.length(mom_visc)
density = fluid_density / wp.max(wp.static(1e-10), norm)

mom_sq = wp.vec3(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

-density * wp.cw_mul(wp.cw_mul(ang, mom_coef), mom_coef)

Comment thread mujoco_warp/_src/derivative.py Outdated

proj_denom = aa * xx + bb * yy + cc * zz
proj_num = a * xx + b * yy + c * zz
dA_coef = wp.pi / wp.max(wp.static(1e-10), wp.sqrt(proj_num * proj_num * proj_num * proj_denom))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lets utilize MJ_MINVAL

Comment thread mujoco_warp/_src/derivative.py Outdated
proj_num = a * xx + b * yy + c * zz
dA_coef = wp.pi / wp.max(wp.static(1e-10), wp.sqrt(proj_num * proj_num * proj_num * proj_denom))

A_proj = wp.pi * wp.sqrt(proj_denom / wp.max(wp.static(1e-10), proj_num))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lets utilize MJ_MINVAL

Comment thread mujoco_warp/_src/derivative.py Outdated
A_proj = wp.pi * wp.sqrt(proj_denom / wp.max(wp.static(1e-10), proj_num))

norm = wp.sqrt(xx + yy + zz)
inv_norm = 1.0 / wp.max(wp.static(1e-10), norm)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lets utilize MJ_MINVAL

Comment thread mujoco_warp/_src/derivative.py Outdated
xz, yz, zz + inner
)

D = D * (-quad_coef * inv_norm)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

*=

Comment thread mujoco_warp/_src/derivative.py Outdated
proj_num = a * xx + b * yy + c * zz
norm2 = xx + yy + zz
df_denom = wp.pi * kutta_lift_coef * fluid_density / wp.max(
wp.static(1e-10), wp.sqrt(proj_denom * proj_num * norm2)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

MJ_MINVAL

Comment thread mujoco_warp/_src/derivative.py Outdated
dfx_coef = yy * (a - b) + zz * (a - c)
dfy_coef = xx * (b - a) + zz * (b - c)
dfz_coef = xx * (c - a) + yy * (c - b)
proj_term = proj_num / wp.max(wp.static(1e-10), proj_denom)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

MJ_MINVAL

Comment thread mujoco_warp/_src/derivative.py Outdated
dfy_coef = xx * (b - a) + zz * (b - c)
dfz_coef = xx * (c - a) + yy * (c - b)
proj_term = proj_num / wp.max(wp.static(1e-10), proj_denom)
cos_term = proj_num / wp.max(wp.static(1e-10), norm2)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

MJ_MINVAL

Comment thread mujoco_warp/_src/derivative.py Outdated
proj_term = proj_num / wp.max(wp.static(1e-10), proj_denom)
cos_term = proj_num / wp.max(wp.static(1e-10), norm2)

D = wp.mat33(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

a - a, b - b and c - c can be replaced with 0.0

Comment thread mujoco_warp/_src/derivative.py Outdated
a - b, b - b, c - b,
a - c, b - c, c - c
)
D = D * (wp.static(2.0) * proj_num)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

*= and we can remove the parentheses

Comment thread mujoco_warp/_src/derivative.py Outdated
)
D = D * (wp.static(2.0) * proj_num)

inner_term = wp.vec3(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we can utilize wp.cw_mul here

Comment thread mujoco_warp/_src/derivative.py Outdated
lin_vel_scaled = lin_vel * magnus_coef
ang_vel_scaled = ang_vel * magnus_coef

D_ang = _cross_deriv_a(ang_vel_scaled, lin_vel)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should lin_vel -> lin_vel_scaled?

Comment thread mujoco_warp/_src/derivative.py Outdated
ang_vel_scaled = ang_vel * magnus_coef

D_ang = _cross_deriv_a(ang_vel_scaled, lin_vel)
D_lin = _cross_deriv_b(ang_vel, lin_vel_scaled)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should ang_vel -> ang_vel_scaled?

Comment thread mujoco_warp/_src/derivative.py Outdated


@wp.func
def _cross_deriv_a(a: wp.vec3, b: wp.vec3) -> wp.mat33:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lets consider combining _cross_deriv_a and _cross_deriv_b into one function that returns 2 wp.mat33 since it looks like we always compute derivatives wrt to both cross product inputs

Copy link
Copy Markdown
Collaborator

@thowell thowell left a comment

Choose a reason for hiding this comment

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

@Aaryan-549 thank you for contributing this pr!

in addition to the comments, lets add a test. please let us know if you have any questions. thanks!

@Aaryan-549
Copy link
Copy Markdown
Contributor Author

Hey @thowell, really sorry for the delay. I have implemented all fixes that you asked for. Let me know If there are any other changes needed.

@erikfrey
Copy link
Copy Markdown
Collaborator

erikfrey commented Jan 5, 2026

@Aaryan-549 thank you for the contribution. It looks like there are some ruff linter issues, kernel analyzer issues, and unit test failures.

You should be able to run these three tools locally to reproduce and fix the errors reported in CI. Please give that a go - once the issues are fixed we'll take another look at the PR.

ruff and pytest issues should be straightforward. To install and use the kernel analyzer, see the readme here.

@Aaryan-549
Copy link
Copy Markdown
Contributor Author

Thanks, apologies for the noise. I'll run the tools locally and fix the errors shortly.

@Aaryan-549
Copy link
Copy Markdown
Contributor Author

I've run all three tools locally and fixed the issues.

Ruff formatting and linting both pass. I've fixed 21 failing tests and now have 925/926 tests passing. The one remaining failure (test_collision19) is a pre-existing collision bug that was already failing before my commits.

The kernel analyzer shows 3 style warnings in my code - two missing "# In:" comments and one parameter ordering convention issue. These don't break anything but I can fix them if you'd like, or address them in a follow-up after review.

@thowell
Copy link
Copy Markdown
Collaborator

thowell commented Jan 13, 2026

@Aaryan-549 thank you for the update!

all of the checks should pass including tests, formatting, and the linter. pre-commit will provide information about what should be fixed, please resolve any issues this tool reports.

thanks!

mjw.step(m, d)
self.assertGreater(d.time.numpy()[0], 0.0)

@parameterized.product(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

since the implicit integrator is not implemented in this pr we can remove this test

Comment thread mujoco_warp/_src/derivative_test.py Outdated
_assert_eq(mjw_out, mj_out, "qM - dt * qDeriv")

@parameterized.parameters(
(mujoco.mjtJacobian.mjJAC_DENSE, "ellipsoid"),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

no need to parameterized 'fluidshape' since both cases are ellipsoid

Comment thread mujoco_warp/_src/derivative_test.py Outdated
<site name="site2" pos="0 0 1"/>
</body>
</worldbody>
<tendon>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

do we need tendons for this test?

Comment thread mujoco_warp/_src/derivative_test.py
@SUZ-tsinghua
Copy link
Copy Markdown

Hi @thowell , I'd happy to review this pr. @Aaryan-549 For the derivative test, there is no need to include tendon and actuator. You can just copy my test.

@Aaryan-549
Copy link
Copy Markdown
Contributor Author

Thanks @thowell! I've addressed all the latest feedback in the recent push:

  • Reverted changes to io.py, io_test.py, and forward_test.py. I agree it's better to keep the implicit integrator support for a separate PR.
  • Simplified derivative_test.py by removing unnecessary tendons, actuators, and the redundant fluidshape parameterization.
  • Removed unnecessary tendons and actuators from the test XML as suggested.
  • Reverted the unrelated formatting changes in kernel_analyzer.

Checks are passing. Ready for final review!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

please revert all changes to this file

Comment thread mujoco_warp/_src/io.py
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we shouldn't need any changes to this file

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we shouldn't need any changes to this file

@Aaryan-549 Aaryan-549 force-pushed the feature/add-mjd-ellipsoidfluid-implementation branch 2 times, most recently from e618379 to 7ecd897 Compare January 23, 2026 19:19
@Aaryan-549
Copy link
Copy Markdown
Contributor Author

Hey @thowell ,

I am really sorry for taking a whole week to reply back but I've been working on implementing the mjd_ellipsoidFluid derivative for PR #897, and I've run into a persistent issue that I could use some guidance on.

The Problem:
The test_smooth_vel_fluid tests are failing with ~50% of matrix elements mismatched. The diagonal elements match perfectly, but the off-diagonal elements have incorrect values. I've traced through the code extensively and believe the issue may be related to coordinate frame conventions or matrix storage order differences between MuJoCo and Warp.

What I've Verified/Fixed:

  • Integrator parameter type (changed from wp.array(dtype=int) to int)
  • Integrator enum check (using == 2 for IMPLICITFAST)
  • Dense vs sparse iteration (created separate kernels to iterate over all nv×nv DOF pairs for dense mode)
  • Attempted to match MuJoCo's column-major B matrix storage by transposing D in _add_to_quadrant

Current State:
The B matrix derivative functions (_added_mass_forces_deriv, _viscous_drag_deriv, etc.) appear to match MuJoCo's implementations, and the Jacobian computation follows the same approach. However, something about how the pieces fit together is producing wrong off-diagonal values.

Side Note:
I also noticed that when I ran @SUZ-tsinghua's original branch locally, there were 32 failing tests out of the box. Were the tests passing on your end when you reviewed? Just want to make sure I'm not chasing issues that existed before my changes.

Any pointers on what might be causing the mismatch would be really appreciated. Happy to hop on a call if that would be easier.

Thanks!

@SUZ-tsinghua
Copy link
Copy Markdown

Hi @Aaryan-549 , on my side, I only encountered 3 failed io tests on my branch. I have fixed these errors by merging the original branch into my branch.

@Aaryan-549
Copy link
Copy Markdown
Contributor Author

Hey @SUZ-tsinghua even I am facing 3 failed tests on my end(for my code). Do you have any idea of what could be causing these?(we only need to take care of 2 as 1 of the test was failing in main too, so I don't think we caused it).

Implements derivative of ellipsoid-based fluid forces with respect to velocities.
Includes all component derivatives:
- Added mass forces
- Viscous torque and drag
- Kutta lift
- Magnus force

The implementation adds the fluid force derivatives to qDeriv, following the
pattern from the reference C implementation.
…J_MINVAL, restructure density checks, combine cross derivatives
@thowell thowell force-pushed the feature/add-mjd-ellipsoidfluid-implementation branch 6 times, most recently from d32f862 to 4fedaf7 Compare April 29, 2026 15:46
@thowell thowell force-pushed the feature/add-mjd-ellipsoidfluid-implementation branch from 4fedaf7 to fb1b9c0 Compare April 29, 2026 16:18
@thowell
Copy link
Copy Markdown
Collaborator

thowell commented Apr 29, 2026

@Aaryan-549 updated the pr branch. please take a look at the changes. thanks!

@Aaryan-549
Copy link
Copy Markdown
Contributor Author

@thowell Thanks for the changes. I'll take a look at them shortly.

@Aaryan-549
Copy link
Copy Markdown
Contributor Author

Looks good to me, Thanks a lot for the assist!

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.

add implementation of mjd_ellipsoidFluid

4 participants