1use crate::geometry::{get_frame_error, invert_frame, new_ref_point, Frame, Introspection, Twist};
18use crate::joint::{Joint, JointType};
19use serde::{Deserialize, Serialize};
20
21pub type RigidBodyInertia = f64;
24
25#[derive(Copy, Clone, Debug, Deserialize, Serialize)]
31pub struct Segment {
32 joint: Joint,
33 f_tip: Frame,
34 inertia: RigidBodyInertia,
35}
36
37impl Segment {
38 pub fn default() -> Segment {
40 Segment {
41 joint: Joint::default(),
42 f_tip: Frame::identity(),
43 inertia: 0.0,
44 }
45 }
46
47 pub fn new(joint: Joint, f_tip: Frame, inertia: RigidBodyInertia) -> Segment {
50 let frame = invert_frame(joint.pose(0.0)) * f_tip;
51 Segment {
52 joint: joint,
53 f_tip: frame,
54 inertia: inertia,
55 }
56 }
57
58 pub fn set_joint(&self, new_joint: Joint) -> Segment {
60 Segment {
61 joint: new_joint,
62 f_tip: self.f_tip,
63 inertia: self.inertia,
64 }
65 }
66
67 pub fn set_tip_frame(&self, new_f_tip: Frame) -> Segment {
69 let frame = invert_frame(self.joint.pose(0.0)) * new_f_tip;
70 Segment {
71 joint: self.joint,
72 f_tip: frame,
73 inertia: self.inertia,
74 }
75 }
76
77 pub fn set_inertia(&self, new_inertia: RigidBodyInertia) -> Segment {
82 Segment {
83 joint: self.joint,
84 f_tip: self.f_tip,
85 inertia: new_inertia,
86 }
87 }
88
89 pub fn get_joint_type(&self) -> JointType {
91 self.joint.get_joint_type()
92 }
93
94 pub fn get_link_transform(&self) -> Frame {
96 self.f_tip
97 }
98
99 pub fn pose(&self, joint_state: f64) -> Frame {
101 self.joint.pose(joint_state) * self.f_tip
102 }
103
104 pub fn twist(&self, joint_state: f64, qdot: f64) -> Twist {
106 new_ref_point(
107 self.joint.twist(qdot),
108 self.joint.pose(joint_state).get_rotation() * self.f_tip.get_translation(),
109 )
110 }
111}
112
113impl PartialEq for Segment {
114 fn eq(&self, other: &Self) -> bool {
115 let threshold = 0.0000001;
116 let similar_tf = get_frame_error(self.f_tip, other.f_tip) < threshold;
117 (self.joint == other.joint) && (self.inertia == other.inertia) && similar_tf
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use crate::geometry::{get_frame_error, get_twist_error, Frame, Twist};
124 use crate::joint::{Joint, JointType};
125 use crate::segment::Segment;
126 use nalgebra::geometry::{Isometry3, Translation3, UnitQuaternion};
127
128 #[test]
129 fn calculate_pose() {
130 let joint = Joint::default()
131 .set_type(JointType::RotZ)
132 .set_offset(2.36)
133 .set_scale(3.5);
134 let f_tip = Isometry3::from_parts(
135 Translation3::new(0.1, -2.0, 0.5),
136 UnitQuaternion::from_euler_angles(1.0, 0.5, -0.4),
137 )
138 .to_homogeneous();
139 let joint_state = 2.1;
140 let segment = Segment::new(joint, f_tip, 0.0);
141 let result = Frame::new(
142 0.689601, -0.0171617, 0.723987, 1.79963, 0.542773, 0.674079, -0.501015, -0.878265,
143 -0.479426, 0.73846, 0.47416, 0.5, 0.0, 0.0, 0.0, 1.0,
144 );
145 let error = get_frame_error(result, segment.pose(joint_state));
146 assert!(error < 0.00001);
147 }
148
149 #[test]
150 fn calculate_twist() {
151 let joint = Joint::default()
152 .set_type(JointType::RotZ)
153 .set_offset(2.36)
154 .set_scale(3.5);
155 let f_tip = Isometry3::from_parts(
156 Translation3::new(0.1, -2.0, 0.5),
157 UnitQuaternion::from_euler_angles(1.0, 0.5, -0.4),
158 )
159 .to_homogeneous();
160 let joint_state = 2.1;
161 let qdot = 0.3;
162 let segment = Segment::new(joint, f_tip, 0.0);
163 let result = Twist::new(0.92217, 1.88961, 0.0, 0.0, 0.0, 1.05);
164 let error = get_twist_error(result, segment.twist(joint_state, qdot));
165 assert!(error < 0.001);
166 }
167}