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