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
use errors::*;
use na::{Isometry3, Real, Translation3, Unit, UnitQuaternion, Vector3};
#[derive(Copy, Debug, Clone)]
pub enum JointType<T: Real> {
Fixed,
Rotational { axis: Unit<Vector3<T>> },
Linear { axis: Unit<Vector3<T>> },
}
#[derive(Copy, Debug, Clone)]
pub struct Range<T: Real> {
pub min: T,
pub max: T,
}
impl<T> Range<T>
where
T: Real,
{
pub fn new(min: T, max: T) -> Self {
Range { min: min, max: max }
}
pub fn is_valid(&self, val: T) -> bool {
val <= self.max && val >= self.min
}
}
#[derive(Debug, Clone)]
pub struct Joint<T: Real> {
pub name: String,
pub joint_type: JointType<T>,
angle: T,
pub limits: Option<Range<T>>,
}
impl<T> Joint<T>
where
T: Real,
{
pub fn new(name: &str, joint_type: JointType<T>) -> Joint<T> {
Joint {
name: name.to_string(),
joint_type: joint_type,
angle: T::zero(),
limits: None,
}
}
pub fn set_angle(&mut self, angle: T) -> Result<(), JointError> {
if let JointType::Fixed = self.joint_type {
return Err(JointError::OutOfLimit);
}
if let Some(range) = self.limits.clone() {
if !range.is_valid(angle) {
return Err(JointError::OutOfLimit);
}
}
self.angle = angle;
Ok(())
}
pub fn angle(&self) -> Option<T> {
match self.joint_type {
JointType::Fixed => None,
_ => Some(self.angle),
}
}
pub fn transform(&self) -> Isometry3<T> {
match self.joint_type {
JointType::Fixed => Isometry3::identity(),
JointType::Rotational { axis } => Isometry3::from_parts(
Translation3::new(T::zero(), T::zero(), T::zero()),
UnitQuaternion::from_axis_angle(&axis, self.angle),
),
JointType::Linear { axis } => Isometry3::from_parts(
Translation3::from_vector(axis.unwrap() * self.angle),
UnitQuaternion::identity(),
),
}
}
}