Closed torkeldanielsson closed 5 months ago
Update on this: it seems I used too few substeps for the simulation. Allowing more substeps makes things better. Still seeing undesired behaviour when lifting things up with the forks though...
I'm also running into problems with revolute joints. There's movement without a reason and constraints being ignored...
Here's a clip:
https://github.com/dimforge/rapier/assets/33688001/78d3f40b-45ba-49d3-a670-a3289bfc7392
This is with no extra forces, default integrator parameters and dt = 1.0/60.0
```rust
use std::f32::consts::FRAC_PI_2 as RIGHT_ANGLE;
use rapier3d::pipeline::{DebugRenderBackend, DebugRenderPipeline};
use rapier3d::prelude::*;
const WHEEL_RADIUS: f32 = 0.1;
const WHEEL_WIDTH: f32 = 0.05;
const AXLE_LENGTH: f32 = 0.5;
const AXLE_DISTANCE: f32 = 0.4;
const FRAME_WIDTH: f32 = 0.04;
pub struct Simulation {
physics: Physics,
}
impl Simulation {
pub fn new() -> Self {
let mut physics = Physics::new();
// Ground
let ground_collider = ColliderBuilder::cuboid(2.0, 0.1, 2.0)
.translation(vector![0.0, -0.1, 0.0])
.build();
physics.collider_set.insert(ground_collider);
// Frame
let frame_body = RigidBodyBuilder::dynamic()
.translation(vector![0.0, WHEEL_RADIUS, 0.0])
.build();
let frame_handle = physics.rigid_body_set.insert(frame_body);
let frame_collider = ColliderBuilder::cuboid(0.05, 0.05, 0.05)
.translation(vector![0.0, 0.0, AXLE_DISTANCE / 2.0])
.density(100.0)
.build();
physics.collider_set.insert_with_parent(
frame_collider,
frame_handle,
&mut physics.rigid_body_set,
);
// Back wheels
let back_left_wheel_body = RigidBodyBuilder::dynamic()
.translation(vector![AXLE_LENGTH / 2.0, WHEEL_RADIUS, 0.0])
.build();
let back_right_wheel_body = RigidBodyBuilder::dynamic()
.translation(vector![-AXLE_LENGTH / 2.0, WHEEL_RADIUS, 0.0])
.build();
let back_left_wheel_collider = ColliderBuilder::cylinder(WHEEL_WIDTH / 2.0, WHEEL_RADIUS)
.rotation(Vector::z() * RIGHT_ANGLE)
.build();
let back_right_wheel_collider = ColliderBuilder::cylinder(WHEEL_WIDTH / 2.0, WHEEL_RADIUS)
.rotation(Vector::z() * RIGHT_ANGLE)
.build();
let back_left_wheel_joint = RevoluteJointBuilder::new(Vector::x_axis())
.local_anchor1(point![AXLE_LENGTH / 2.0, 0.0, 0.0])
.build();
let back_right_wheel_joint = RevoluteJointBuilder::new(Vector::x_axis())
.local_anchor1(point![-AXLE_LENGTH / 2.0, 0.0, 0.0])
.build();
let back_left_wheel_handle = physics.rigid_body_set.insert(back_left_wheel_body);
physics.collider_set.insert_with_parent(
back_left_wheel_collider,
back_left_wheel_handle,
&mut physics.rigid_body_set,
);
physics.multibody_joint_set.insert(
frame_handle,
back_left_wheel_handle,
back_left_wheel_joint,
true,
);
let back_right_wheel_handle = physics.rigid_body_set.insert(back_right_wheel_body);
physics.collider_set.insert_with_parent(
back_right_wheel_collider,
back_right_wheel_handle,
&mut physics.rigid_body_set,
);
physics.multibody_joint_set.insert(
frame_handle,
back_right_wheel_handle,
back_right_wheel_joint,
true,
);
// Front wheel
let front_wheel_diameter = WHEEL_RADIUS - FRAME_WIDTH / 2.0;
let front_wheel_body = RigidBodyBuilder::dynamic()
.translation(vector![0.0, front_wheel_diameter / 2.0, AXLE_DISTANCE])
.build();
let front_wheel_collider =
ColliderBuilder::cylinder(WHEEL_WIDTH / 4.0, front_wheel_diameter / 2.0)
.rotation(Vector::z() * RIGHT_ANGLE)
.friction(0.0)
.friction_combine_rule(CoefficientCombineRule::Min)
.build();
let front_wheel_joint = RevoluteJointBuilder::new(Vector::x_axis())
.local_anchor1(point![
0.0,
-(front_wheel_diameter + FRAME_WIDTH) / 2.0,
AXLE_DISTANCE
])
.build();
let front_wheel_handle = physics.rigid_body_set.insert(front_wheel_body);
physics.collider_set.insert_with_parent(
front_wheel_collider,
front_wheel_handle,
&mut physics.rigid_body_set,
);
physics.multibody_joint_set.insert(
frame_handle,
front_wheel_handle,
front_wheel_joint,
true,
);
Simulation { physics }
}
pub fn step(&mut self, dt: f32) {
self.physics.step(dt);
}
pub fn reset(&mut self) {
*self = Simulation::new();
}
pub fn debug_render(&mut self, renderer: &mut impl DebugRenderBackend) {
self.physics.debug_render(renderer);
}
}
struct Physics {
rigid_body_set: RigidBodySet,
collider_set: ColliderSet,
gravity: Vector
If helpful I could post a full project.
Did I make a mistake somewhere or are revolute joints broken?
Please try again with the latest rapier version. It has a new constraints solver that improved joint convergence. I’m closing this now, but feel free to open a new issue with a tets case if that happens again.
I am trying to create a vehicle and my approach is to use a
RigidBody
for each of:RigidBody
which is used for steeringI then set up revolute joints for the wheels and the steering. When I apply steering using
set_motor_position
and throttle/brake usingset_motor_velicity
I get the expected result if I let things hover in the air with no ground contact: https://user-images.githubusercontent.com/634877/210060114-e120e304-5c10-478d-8323-8b1f28a0a2fe.mp4But, when I drop it to the ground it starts behaving super weird, glitching and twitching and rolling back and forth: https://user-images.githubusercontent.com/634877/210060212-96a725d8-5b99-49db-b7b1-1ff7ea4c2012.mp4 (Sorry for shakiness from filming screen, hopefully the glitches are obvious... And this is after reducing the weight of things drastically - at higher weights it was really nuts!)
Now, my main question here is to check that I am not totally on a wrong track with this? It seems logical to be able to use revolute joints like this. But even without steering, just four wheels, if I set ridiculous amount for
max_motor_force
andset_motor_velocity
to zero this thing will still creep slowly and randomly back and forth.... That to me seems like I have some major misunderstanding what revolute joints can be used for? Are they only for "show" and can't handle contact with ground?Then I also have a minor separate question - how am I to retrieve a joint so I can set speed for it during the update loop, given a
MultibodyJointHandle
? I came up with this code:The call there to
link_mut(3)
... that surely is not correct 😅