Access Joint during Simulation

Hey,
In my program i use the RevoluteJoint to build a multibody. These multijoints have a motor. Everything works until here. What i would like to know is how can i access the motors and change their values during simulation. E.g. if a user is controlling a car and the wheels are connected to the mainbody of the car and he increases the velocity during simulation.
I guess there might be a way using the bodyset and maybe handles? However i can not figure it out.
Thanks in advance

Hi!

You can follow that example which enables/disables a motor depending on the position of a pin-slot joint. The following snippet assumes your multibody has the handle multibody_handle and the multibody link which has the joint you want to modify is the link_id-th:

let link = body_set.multibody_mut(multibody_handle).and_then(|mb| mb.link_mut(link_id));
if let Some(revolute) = link {
    let joint = levolute
        .joint_mut()
        .downcast_mut::<RevoluteJoint<f32>>()
        .unwrap();
    // Do something with the joint.
}

Note that the velocity of the joint are not stored on the joint itself. So if you need to change the joint’s velocity directly, you can use that:

let mut joint_velocity = multibody.joint_velocity_mut(link_id);
joint_velocity[0] = 10.0;

In your case, since the revolute joint has only one degree-of-freedom, the returned vector will have only one component.

1 Like

Thanks a lot. That already was a big help and worked so far. Could you also show how you could iterate through the bodyset and manipulate all revolute motors that you can find? That would be a big help.
Thank you!

In the following, assuming bodies is a DefaultBodySet, you can do:

for (handle, body) in bodies.iter() {
    if let Some(multibody) = body.downcast_ref::<Multibody<f32>>() {
        for joint in multibody.links().filter_map(|l| l.joint().downcast_ref::<RevoluteJoint<f32>>()) {
            // Do something.
        }
    }
}

If you need mutable references, you would do:

for (handle, body) in bodies.iter_mut() {
    if let Some(multibody) = body.downcast_mut::<Multibody<f32>>() {
        for joint in multibody.links_mut().filter_map(|l| l.joint_mut().downcast_mut::<RevoluteJoint<f32>>()) {
            // Do something.
        }
    }
}

However you can’t because there is no .links_mut() method on multibodies. This is an oversight so I’ve opened a PR that adds it: https://github.com/rustsim/nphysics/pull/224

EDIT: this PR is now merged and released with nphysics2d and nphysics3d 0.12.3. So a cargo update should be enough for you to be able to use the mutable iteration mentioned above.

Thanls a lot, this is exactly what i was looking for!