box2d_rs/private/dynamics/joints/
b2_motor_joint.rs

1use crate::b2_math::*;
2use crate::b2_common::*;
3use crate::b2rs_common::UserDataType;
4use crate::b2_time_step::*;
5use crate::joints::b2_motor_joint::*;
6
7// Point-to-point constraint
8// cdot = v2 - v1
9//      = v2 + cross(w2, r2) - v1 - cross(w1, r1)
10// J = [-i -r1_skew i r2_skew ]
11// Identity used:
12// w k % (rx i + ry j) = w * (-ry i + rx j)
13//
14// r1 = offset - c1
15// r2 = -c2
16
17// Angle constraint
18// cdot = w2 - w1
19// J = [0 0 -1 0 0 1]
20// k = invI1 + invI2
21
22pub(crate) fn init_velocity_constraints<D: UserDataType>(
23	self_: &mut B2motorJoint<D>,
24	data: &B2solverData,
25	positions: &[B2position],
26	velocities: &mut [B2velocity],
27) {
28	{
29		let m_body_a = self_.base.m_body_a.borrow();
30		let m_body_b = self_.base.m_body_b.borrow();
31		self_.m_index_a = m_body_a.m_island_index;
32		self_.m_index_b = m_body_b.m_island_index;
33		self_.m_local_center_a = m_body_a.m_sweep.local_center;
34		self_.m_local_center_b = m_body_b.m_sweep.local_center;
35		self_.m_inv_mass_a = m_body_a.m_inv_mass;
36		self_.m_inv_mass_b = m_body_b.m_inv_mass;
37		self_.m_inv_ia = m_body_a.m_inv_i;
38		self_.m_inv_ib = m_body_b.m_inv_i;
39	}
40
41	let c_a: B2vec2 = positions[self_.m_index_a as usize].c;
42	let a_a: f32 = positions[self_.m_index_a as usize].a;
43	let mut v_a: B2vec2 = velocities[self_.m_index_a as usize].v;
44	let mut w_a: f32 = velocities[self_.m_index_a as usize].w;
45
46	let c_b: B2vec2 = positions[self_.m_index_b as usize].c;
47	let a_b: f32 = positions[self_.m_index_b as usize].a;
48	let mut v_b: B2vec2 = velocities[self_.m_index_b as usize].v;
49	let mut w_b: f32 = velocities[self_.m_index_b as usize].w;
50
51	let (q_a, q_b) = (B2Rot::new(a_a), B2Rot::new(a_b));
52
53	// Compute the effective mass matrix.
54	self_.m_r_a = b2_mul_rot_by_vec2(q_a, self_.m_linear_offset - self_.m_local_center_a);
55	self_.m_r_b = b2_mul_rot_by_vec2(q_b, -self_.m_local_center_b);
56
57	// J = [-i -r1_skew i r2_skew]
58	// r_skew = [-ry; rx]
59
60	// Matlab
61	// k = [ m_a+r1y^2*i_a+m_b+r2y^2*i_b,  -r1y*i_a*r1x-r2y*i_b*r2x,          -r1y*i_a-r2y*i_b]
62	//     [  -r1y*i_a*r1x-r2y*i_b*r2x, m_a+r1x^2*i_a+m_b+r2x^2*i_b,           r1x*i_a+r2x*i_b]
63	//     [          -r1y*i_a-r2y*i_b,           r1x*i_a+r2x*i_b,                   i_a+i_b]
64
65	let m_a: f32 = self_.m_inv_mass_a;
66	let m_b: f32 = self_.m_inv_mass_b;
67	let i_a: f32 = self_.m_inv_ia;
68	let i_b: f32 = self_.m_inv_ib;
69
70	// Upper 2 by 2 of k for point to point
71	let mut k = B2Mat22::default();
72	k.ex.x = m_a + m_b + i_a * self_.m_r_a.y * self_.m_r_a.y + i_b * self_.m_r_b.y * self_.m_r_b.y;
73	k.ex.y = -i_a * self_.m_r_a.x * self_.m_r_a.y - i_b * self_.m_r_b.x * self_.m_r_b.y;
74	k.ey.x = k.ex.y;
75	k.ey.y = m_a + m_b + i_a * self_.m_r_a.x * self_.m_r_a.x + i_b * self_.m_r_b.x * self_.m_r_b.x;
76
77	self_.m_linear_mass = k.get_inverse();
78
79	self_.m_angular_mass = i_a + i_b;
80	if self_.m_angular_mass > 0.0 {
81		self_.m_angular_mass = 1.0 / self_.m_angular_mass;
82	}
83
84	self_.m_linear_error = c_b + self_.m_r_b - c_a - self_.m_r_a;
85	self_.m_angular_error = a_b - a_a - self_.m_angular_offset;
86
87	if data.step.warm_starting {
88		// Scale impulses to support a variable time step.
89		self_.m_linear_impulse *= data.step.dt_ratio;
90		self_.m_angular_impulse *= data.step.dt_ratio;
91
92		let p = B2vec2::new(self_.m_linear_impulse.x, self_.m_linear_impulse.y);
93		v_a -= m_a * p;
94		w_a -= i_a * (b2_cross(self_.m_r_a, p) + self_.m_angular_impulse);
95		v_b += m_b * p;
96		w_b += i_b * (b2_cross(self_.m_r_b, p) + self_.m_angular_impulse);
97	} else {
98		self_.m_linear_impulse.set_zero();
99		self_.m_angular_impulse = 0.0;
100	}
101
102	velocities[self_.m_index_a as usize].v = v_a;
103	velocities[self_.m_index_a as usize].w = w_a;
104	velocities[self_.m_index_b as usize].v = v_b;
105	velocities[self_.m_index_b as usize].w = w_b;
106}
107
108pub(crate) fn solve_velocity_constraints<D: UserDataType>(
109	self_: &mut B2motorJoint<D>,
110	data: &B2solverData,
111	velocities: &mut [B2velocity],
112) {
113	let B2velocity {
114		v: mut v_a,
115		w: mut w_a,
116	} = velocities[self_.m_index_a as usize];
117	// let mut v_a: B2vec2 =velocities[self_.m_index_a as usize].v;
118	// let mut w_a: f32 =velocities[self_.m_index_a as usize].w;
119
120	//TODO_humman - optimize others like this
121	let B2velocity {
122		v: mut v_b,
123		w: mut w_b,
124	} = velocities[self_.m_index_b as usize];
125	// let mut v_b: B2vec2 =velocities[self_.m_index_b as usize].v;
126	// let mut w_b: f32 =velocities[self_.m_index_b as usize].w;
127
128	//TODO_humman - optimize others like this
129	let B2motorJoint {
130		m_inv_mass_a: m_a,
131		m_inv_mass_b: m_b,
132		m_inv_ia: i_a,
133		m_inv_ib: i_b,
134		..
135	} = *self_;
136	// let m_a:f32 = self_.m_inv_mass_a;
137	// let m_b: f32 =self_.m_inv_mass_b;
138	// let i_a: f32 = self_.m_inv_ia;
139	// let i_b: f32 =self_.m_inv_ib;
140
141	let h: f32 = data.step.dt;
142	let inv_h: f32 = data.step.inv_dt;
143
144	// solve angular friction
145	{
146		let cdot: f32 = w_b - w_a + inv_h * self_.m_correction_factor * self_.m_angular_error;
147		let mut impulse: f32 = -self_.m_angular_mass * cdot;
148
149		let old_impulse: f32 = self_.m_angular_impulse;
150		let max_impulse: f32 = h * self_.m_max_torque;
151		self_.m_angular_impulse =
152			b2_clamp(self_.m_angular_impulse + impulse, -max_impulse, max_impulse);
153		impulse = self_.m_angular_impulse - old_impulse;
154
155		w_a -= i_a * impulse;
156		w_b += i_b * impulse;
157	}
158
159	// solve linear friction
160	{
161		let cdot: B2vec2 = v_b + b2_cross_scalar_by_vec(w_b, self_.m_r_b)
162			- v_a - b2_cross_scalar_by_vec(w_a, self_.m_r_a)
163			+ inv_h * self_.m_correction_factor * self_.m_linear_error;
164
165		let mut impulse: B2vec2 = -b2_mul(self_.m_linear_mass, cdot);
166		let old_impulse: B2vec2 = self_.m_linear_impulse;
167		self_.m_linear_impulse += impulse;
168
169		let max_impulse: f32 = h * self_.m_max_force;
170
171		if self_.m_linear_impulse.length_squared() > max_impulse * max_impulse {
172			self_.m_linear_impulse.normalize();
173			self_.m_linear_impulse *= max_impulse;
174		}
175
176		impulse = self_.m_linear_impulse - old_impulse;
177
178		v_a -= m_a * impulse;
179		w_a -= i_a * b2_cross(self_.m_r_a, impulse);
180
181		v_b += m_b * impulse;
182		w_b += i_b * b2_cross(self_.m_r_b, impulse);
183	}
184
185	velocities[self_.m_index_a as usize].v = v_a;
186	velocities[self_.m_index_a as usize].w = w_a;
187	velocities[self_.m_index_b as usize].v = v_b;
188	velocities[self_.m_index_b as usize].w = w_b;
189}
190
191pub(crate) fn solve_position_constraints<D: UserDataType>(
192	_self: &B2motorJoint<D>,
193	data: &B2solverData,
194	_positions: &mut [B2position],
195) -> bool {
196	b2_not_used(data);
197
198	return true;
199}