rapier3d/dynamics/solver/
velocity_solver.rs1use crate::dynamics::solver::JointConstraintsSet;
2use crate::dynamics::solver::contact_constraint::ContactConstraintsSet;
3use crate::dynamics::solver::solver_body::SolverBodies;
4use crate::dynamics::{
5 IntegrationParameters, IslandManager, JointGraphEdge, JointIndex, MultibodyJointSet,
6 MultibodyLinkId, RigidBodySet, RigidBodyType, solver::SolverVel,
7};
8use crate::geometry::{ContactManifold, ContactManifoldIndex};
9use crate::math::Real;
10use crate::prelude::RigidBodyVelocity;
11use na::DVector;
12use parry::math::{SIMD_WIDTH, Translation};
13
14#[cfg(feature = "dim3")]
15use crate::dynamics::FrictionModel;
16
17pub(crate) struct VelocitySolver {
18 pub solver_bodies: SolverBodies,
19 pub solver_vels_increment: Vec<SolverVel<Real>>,
20 pub generic_solver_vels: DVector<Real>,
21 pub generic_solver_vels_increment: DVector<Real>,
22 pub multibody_roots: Vec<MultibodyLinkId>,
23}
24
25impl VelocitySolver {
26 pub fn new() -> Self {
27 Self {
28 solver_bodies: SolverBodies::default(),
29 solver_vels_increment: Vec::new(),
30 generic_solver_vels: DVector::zeros(0),
31 generic_solver_vels_increment: DVector::zeros(0),
32 multibody_roots: Vec::new(),
33 }
34 }
35
36 pub fn init_constraints(
37 &self,
38 island_id: usize,
39 islands: &IslandManager,
40 bodies: &mut RigidBodySet,
41 multibodies: &mut MultibodyJointSet,
42 manifolds_all: &mut [&mut ContactManifold],
43 manifold_indices: &[ContactManifoldIndex],
44 joints_all: &mut [JointGraphEdge],
45 joint_indices: &[JointIndex],
46 contact_constraints: &mut ContactConstraintsSet,
47 joint_constraints: &mut JointConstraintsSet,
48 #[cfg(feature = "dim3")] friction_model: FrictionModel,
49 ) {
50 contact_constraints.init(
51 island_id,
52 islands,
53 bodies,
54 &self.solver_bodies,
55 multibodies,
56 manifolds_all,
57 manifold_indices,
58 #[cfg(feature = "dim3")]
59 friction_model,
60 );
61
62 joint_constraints.init(
63 island_id,
64 islands,
65 bodies,
66 multibodies,
67 joints_all,
68 joint_indices,
69 );
70 }
71
72 pub fn init_solver_velocities_and_solver_bodies(
73 &mut self,
74 total_step_dt: Real,
75 params: &IntegrationParameters,
76 island_id: usize,
77 islands: &IslandManager,
78 bodies: &mut RigidBodySet,
79 multibodies: &mut MultibodyJointSet,
80 ) {
81 self.multibody_roots.clear();
82 self.solver_bodies.clear();
83
84 let aligned_solver_bodies_len =
85 islands.active_island(island_id).len().div_ceil(SIMD_WIDTH) * SIMD_WIDTH;
86 self.solver_bodies.resize(aligned_solver_bodies_len);
87
88 self.solver_vels_increment.clear();
89 self.solver_vels_increment
90 .resize(aligned_solver_bodies_len, SolverVel::zero());
91
92 let mut multibody_solver_id = 0;
100 for handle in islands.active_island(island_id) {
101 if let Some(link) = multibodies.rigid_body_link(*handle).copied() {
102 let multibody = multibodies
103 .get_multibody_mut_internal(link.multibody)
104 .unwrap();
105
106 if link.id == 0 || link.id == 1 && !multibody.root_is_dynamic {
107 multibody.solver_id = multibody_solver_id;
108 multibody_solver_id += multibody.ndofs() as u32;
109 self.multibody_roots.push(link);
110 }
111 } else {
112 let rb = &bodies[*handle];
113 let solver_vel_incr =
114 &mut self.solver_vels_increment[rb.ids.active_set_offset as usize];
115 self.solver_bodies
116 .copy_from(total_step_dt, rb.ids.active_set_offset as usize, rb);
117
118 solver_vel_incr.angular =
119 rb.mprops.effective_world_inv_inertia * rb.forces.torque * params.dt;
120 solver_vel_incr.linear =
121 rb.forces.force.component_mul(&rb.mprops.effective_inv_mass) * params.dt;
122 }
123 }
124
125 self.generic_solver_vels_increment = DVector::zeros(multibody_solver_id as usize);
127 self.generic_solver_vels = DVector::zeros(multibody_solver_id as usize);
128
129 for link in &self.multibody_roots {
131 let multibody = multibodies
132 .get_multibody_mut_internal(link.multibody)
133 .unwrap();
134 multibody.update_dynamics(params.dt, bodies);
135 multibody.update_acceleration(bodies);
136
137 let mut solver_vels_incr = self
138 .generic_solver_vels_increment
139 .rows_mut(multibody.solver_id as usize, multibody.ndofs());
140 let mut solver_vels = self
141 .generic_solver_vels
142 .rows_mut(multibody.solver_id as usize, multibody.ndofs());
143
144 solver_vels_incr.axpy(params.dt, &multibody.accelerations, 0.0);
145 solver_vels.copy_from(&multibody.velocities);
146 }
147 }
148
149 #[profiling::function]
150 pub fn solve_constraints(
151 &mut self,
152 params: &IntegrationParameters,
153 num_substeps: usize,
154 bodies: &mut RigidBodySet,
155 multibodies: &mut MultibodyJointSet,
156 contact_constraints: &mut ContactConstraintsSet,
157 joint_constraints: &mut JointConstraintsSet,
158 ) {
159 for substep_id in 0..num_substeps {
160 let is_last_substep = substep_id == num_substeps - 1;
161
162 for (solver_vels, incr) in self
164 .solver_bodies
165 .vels
166 .iter_mut()
167 .zip(self.solver_vels_increment.iter())
168 {
169 solver_vels.linear += incr.linear;
170 solver_vels.angular += incr.angular;
171 }
172
173 self.generic_solver_vels += &self.generic_solver_vels_increment;
174
175 joint_constraints.update(params, multibodies, &self.solver_bodies);
179 contact_constraints.update(params, substep_id, multibodies, &self.solver_bodies);
180
181 if params.warmstart_coefficient != 0.0 {
182 contact_constraints
187 .warmstart(&mut self.solver_bodies, &mut self.generic_solver_vels);
188 }
189
190 for _ in 0..params.num_internal_pgs_iterations {
191 joint_constraints.solve(&mut self.solver_bodies, &mut self.generic_solver_vels);
192 contact_constraints.solve(&mut self.solver_bodies, &mut self.generic_solver_vels);
193 }
194
195 self.integrate_positions(params, is_last_substep, bodies, multibodies);
199
200 for _ in 0..params.num_internal_stabilization_iterations {
204 joint_constraints
205 .solve_wo_bias(&mut self.solver_bodies, &mut self.generic_solver_vels);
206 contact_constraints
207 .solve_wo_bias(&mut self.solver_bodies, &mut self.generic_solver_vels);
208 }
209 }
210 }
211
212 #[profiling::function]
213 pub fn integrate_positions(
214 &mut self,
215 params: &IntegrationParameters,
216 is_last_substep: bool,
217 bodies: &mut RigidBodySet,
218 multibodies: &mut MultibodyJointSet,
219 ) {
220 for (solver_vels, solver_pose) in self
221 .solver_bodies
222 .vels
223 .iter()
224 .zip(self.solver_bodies.poses.iter_mut())
225 {
226 let linvel = solver_vels.linear;
227 let angvel = solver_vels.angular;
228
229 let new_vels = RigidBodyVelocity { linvel, angvel };
232 new_vels.integrate_linearized(params.dt, &mut solver_pose.pose);
233 }
234
235 for link in &self.multibody_roots {
259 let multibody = multibodies
260 .get_multibody_mut_internal(link.multibody)
261 .unwrap();
262 let solver_vels = self
263 .generic_solver_vels
264 .rows(multibody.solver_id as usize, multibody.ndofs());
265 multibody.velocities.copy_from(&solver_vels);
266 multibody.integrate(params.dt);
267 multibody.forward_kinematics(bodies, false);
269 multibody.update_rigid_bodies_internal(bodies, !is_last_substep, true, false);
270
271 if !is_last_substep {
272 multibody.update_dynamics(params.dt, bodies);
275 multibody.update_acceleration(bodies);
276
277 let mut solver_vels_incr = self
278 .generic_solver_vels_increment
279 .rows_mut(multibody.solver_id as usize, multibody.ndofs());
280 solver_vels_incr.axpy(params.dt, &multibody.accelerations, 0.0);
281 }
282 }
283 }
284
285 pub fn writeback_bodies(
286 &mut self,
287 params: &IntegrationParameters,
288 islands: &IslandManager,
289 island_id: usize,
290 bodies: &mut RigidBodySet,
291 multibodies: &mut MultibodyJointSet,
292 ) {
293 for handle in islands.active_island(island_id) {
294 let link = if self.multibody_roots.is_empty() {
295 None
296 } else {
297 multibodies.rigid_body_link(*handle).copied()
298 };
299
300 if let Some(link) = link {
301 let multibody = multibodies
302 .get_multibody_mut_internal(link.multibody)
303 .unwrap();
304
305 if link.id == 0 || link.id == 1 && !multibody.root_is_dynamic {
306 let solver_vels = self
307 .generic_solver_vels
308 .rows(multibody.solver_id as usize, multibody.ndofs());
309 multibody.velocities.copy_from(&solver_vels);
310 }
311 } else {
312 let rb = bodies.index_mut_internal(*handle);
313 let solver_vels = &self.solver_bodies.vels[rb.ids.active_set_offset as usize];
314 let solver_poses = &self.solver_bodies.poses[rb.ids.active_set_offset as usize];
315
316 let dangvel = solver_vels.angular;
317
318 let mut new_vels = RigidBodyVelocity {
319 linvel: solver_vels.linear,
320 angvel: dangvel,
321 };
322 new_vels = new_vels.apply_damping(params.dt, &rb.damping);
323
324 rb.vels = new_vels;
325
326 if rb.body_type != RigidBodyType::KinematicPositionBased {
330 rb.pos.next_position =
331 solver_poses.pose * Translation::from(-rb.mprops.local_mprops.local_com);
332 }
333
334 if rb.ccd.ccd_enabled {
335 rb.ccd_vels = rb
338 .pos
339 .interpolate_velocity(params.inv_dt(), rb.local_center_of_mass());
340 } else {
341 rb.ccd_vels = RigidBodyVelocity::zero();
342 }
343 }
344 }
345 }
346}