1use crate::joint::JointType;
18use crate::segment::Segment;
19use nalgebra::DMatrix;
20use serde::{Deserialize, Serialize};
21
22#[derive(Clone, Debug, Deserialize, Serialize)]
31pub struct Chain {
32 segments: Vec<Segment>,
33 num_joints: usize,
34 num_ind_joints: usize,
35 num_unlocked_joints: usize,
36 locked_joints: Vec<bool>,
37 coupling_matrix: DMatrix<f64>,
38}
39
40impl Chain {
41 pub fn default() -> Chain {
43 Chain {
44 segments: Vec::new(),
45 num_joints: 0,
46 num_ind_joints: 0,
47 num_unlocked_joints: 0,
48 locked_joints: vec![],
49 coupling_matrix: DMatrix::identity(0, 0),
50 }
51 }
52
53 pub fn get_num_segments(&self) -> usize {
55 self.segments.len()
56 }
57
58 pub fn get_num_joints(&self) -> usize {
60 self.num_joints
61 }
62
63 pub fn get_num_ind_joints(&self) -> usize {
65 self.num_ind_joints
66 }
67
68 pub fn get_coupling_matrix(&self) -> DMatrix<f64> {
70 self.coupling_matrix.clone()
71 }
72
73 pub fn add_segment(&mut self, segment: Segment) {
76 self.segments.push(segment);
77 if segment.get_joint_type() != JointType::NoJoint {
78 self.num_joints += 1;
79 self.locked_joints.push(false);
80 self.num_unlocked_joints += 1;
81 self.num_ind_joints = self.num_unlocked_joints;
82 self.coupling_matrix = DMatrix::identity(self.num_unlocked_joints, self.num_ind_joints);
83 }
84 }
85
86 pub fn add_chain(&mut self, mut chain: Chain) {
88 self.segments.append(&mut chain.segments);
89 self.num_joints += chain.num_joints;
90 }
91
92 pub fn get_segment(&self, index: usize) -> Segment {
94 self.segments[index]
95 }
96
97 pub fn get_locked_joints(&self) -> Vec<bool> {
99 self.locked_joints.clone()
100 }
101
102 pub fn set_coupling(
104 &mut self,
105 new_locked_joints: Vec<bool>,
106 new_coupling_matrix: DMatrix<f64>,
107 ) {
108 let new_num_unlocked_joints = new_locked_joints.iter().filter(|&n| !(*n)).count();
109 if new_coupling_matrix.nrows() != new_num_unlocked_joints {
110 panic!(
111 "Wrong size of coupling arguments. Matrix has {} rows,
112 but the vector says there should be {}",
113 new_coupling_matrix.nrows(),
114 new_num_unlocked_joints
115 );
116 }
117 self.locked_joints = new_locked_joints;
118 self.num_unlocked_joints = new_num_unlocked_joints;
119 self.num_ind_joints = new_coupling_matrix.ncols();
120 self.coupling_matrix = new_coupling_matrix;
121 }
122}
123
124impl PartialEq for Chain {
125 fn eq(&self, other: &Self) -> bool {
126 (self.segments == other.segments)
127 && (self.num_joints == other.num_joints)
128 && (self.num_ind_joints == other.num_ind_joints)
129 && (self.num_unlocked_joints == other.num_unlocked_joints)
130 && (self.coupling_matrix == other.coupling_matrix)
131 }
132}
133
134#[cfg(test)]
135pub mod tests {
137 use crate::chains::Chain;
138 use crate::geometry::{EulerBuild, Frame};
139 use crate::joint::{Joint, JointType};
140 use crate::segment::Segment;
141
142 pub fn create_testing_chain() -> Chain {
145 let mut chain = Chain::default();
146 chain.add_segment(Segment::new(
148 Joint::default().set_type(JointType::NoJoint),
149 Frame::from_translation_euler(0.1, -0.2, 0.3, -0.1, -0.2, 0.3),
150 0.0,
151 ));
152 chain.add_segment(Segment::new(
154 Joint::default().set_type(JointType::RotZ),
155 Frame::from_translation_euler(0.2, 0.5, 0.1, 0.58, -1.2, 2.3),
156 0.0,
157 ));
158 chain.add_segment(Segment::new(
160 Joint::default().set_type(JointType::RotZ),
161 Frame::from_translation_euler(0.02, 0.3, -0.81, 3.0, -1.7, 1.3),
162 0.0,
163 ));
164 chain.add_segment(Segment::new(
166 Joint::default().set_type(JointType::RotZ),
167 Frame::from_translation_euler(0.4, -0.27, 0.19, 1.57, -1.57, 0.0),
168 0.0,
169 ));
170 chain.add_segment(Segment::new(
172 Joint::default().set_type(JointType::RotZ),
173 Frame::from_translation_euler(0.24, -0.18, 0.16, 0.01, 0.0, -0.01),
174 0.0,
175 ));
176 chain.add_segment(Segment::new(
178 Joint::default().set_type(JointType::RotZ),
179 Frame::from_translation_euler(1.0, -0.5, -0.01, 0.05, -1.02, 0.34),
180 0.0,
181 ));
182 chain.add_segment(Segment::new(
184 Joint::default().set_type(JointType::RotZ),
185 Frame::from_translation_euler(0.02, 0.58, -0.87, 0.95, -1.74, 0.68),
186 0.0,
187 ));
188 chain.add_segment(Segment::new(
190 Joint::default().set_type(JointType::RotZ),
191 Frame::from_translation_euler(0.2, 0.1, -0.1, -0.76, -0.94, 0.25),
192 0.0,
193 ));
194 chain
195 }
196}