1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
use crate::dynamics::SpringModel;
use crate::math::{Isometry, Point, Real, Vector};
use crate::utils::WBasis;
use na::{RealField, Unit, Vector5};
#[derive(Copy, Clone)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct RevoluteJoint {
pub local_anchor1: Point<Real>,
pub local_anchor2: Point<Real>,
pub local_axis1: Unit<Vector<Real>>,
pub local_axis2: Unit<Vector<Real>>,
pub basis1: [Vector<Real>; 2],
pub basis2: [Vector<Real>; 2],
pub impulse: Vector5<Real>,
pub motor_target_vel: Real,
pub motor_target_pos: Real,
pub motor_stiffness: Real,
pub motor_damping: Real,
pub motor_max_impulse: Real,
pub motor_impulse: Real,
pub motor_model: SpringModel,
pub(crate) motor_last_angle: Real,
pub(crate) world_ang_impulse: Vector<Real>,
pub(crate) prev_axis1: Vector<Real>,
}
impl RevoluteJoint {
pub fn new(
local_anchor1: Point<Real>,
local_axis1: Unit<Vector<Real>>,
local_anchor2: Point<Real>,
local_axis2: Unit<Vector<Real>>,
) -> Self {
Self {
local_anchor1,
local_anchor2,
local_axis1,
local_axis2,
basis1: local_axis1.orthonormal_basis(),
basis2: local_axis2.orthonormal_basis(),
impulse: na::zero(),
world_ang_impulse: na::zero(),
motor_target_vel: 0.0,
motor_target_pos: 0.0,
motor_stiffness: 0.0,
motor_damping: 0.0,
motor_max_impulse: Real::MAX,
motor_impulse: 0.0,
prev_axis1: *local_axis1,
motor_model: SpringModel::default(),
motor_last_angle: 0.0,
}
}
pub fn supports_simd_constraints(&self) -> bool {
self.motor_max_impulse == 0.0 || (self.motor_stiffness == 0.0 && self.motor_damping == 0.0)
}
pub fn configure_motor_model(&mut self, model: SpringModel) {
self.motor_model = model;
}
pub fn configure_motor_velocity(&mut self, target_vel: Real, factor: Real) {
self.configure_motor(self.motor_target_pos, target_vel, 0.0, factor)
}
pub fn configure_motor_position(&mut self, target_pos: Real, stiffness: Real, damping: Real) {
self.configure_motor(target_pos, 0.0, stiffness, damping)
}
pub fn configure_motor(
&mut self,
target_pos: Real,
target_vel: Real,
stiffness: Real,
damping: Real,
) {
self.motor_target_vel = target_vel;
self.motor_target_pos = target_pos;
self.motor_stiffness = stiffness;
self.motor_damping = damping;
}
pub fn estimate_motor_angle(
&self,
body_pos1: &Isometry<Real>,
body_pos2: &Isometry<Real>,
) -> Real {
let motor_axis1 = body_pos1 * self.local_axis1;
let ref1 = body_pos1 * self.basis1[0];
let ref2 = body_pos2 * self.basis2[0];
let last_angle_cycles = (self.motor_last_angle / Real::two_pi()).trunc() * Real::two_pi();
let new_angle = if ref1.cross(&ref2).dot(&motor_axis1) < 0.0 {
Real::two_pi() - ref1.angle(&ref2)
} else {
ref1.angle(&ref2)
};
let last_angle_zero_two_pi = self.motor_last_angle - last_angle_cycles;
let mut angle_diff = new_angle - last_angle_zero_two_pi;
if angle_diff > Real::pi() {
angle_diff -= Real::two_pi()
} else if angle_diff < -Real::pi() {
angle_diff += Real::two_pi()
}
self.motor_last_angle + angle_diff
}
}