use crate::joint::JointType;
use crate::segment::Segment;
use nalgebra::DMatrix;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Chain {
segments: Vec<Segment>,
num_joints: usize,
num_ind_joints: usize,
num_unlocked_joints: usize,
locked_joints: Vec<bool>,
coupling_matrix: DMatrix<f64>,
}
impl Chain {
pub fn default() -> Chain {
Chain {
segments: Vec::new(),
num_joints: 0,
num_ind_joints: 0,
num_unlocked_joints: 0,
locked_joints: vec![],
coupling_matrix: DMatrix::identity(0, 0),
}
}
pub fn get_num_segments(&self) -> usize {
self.segments.len()
}
pub fn get_num_joints(&self) -> usize {
self.num_joints
}
pub fn get_num_ind_joints(&self) -> usize {
self.num_ind_joints
}
pub fn get_coupling_matrix(&self) -> DMatrix<f64> {
self.coupling_matrix.clone()
}
pub fn add_segment(&mut self, segment: Segment) {
self.segments.push(segment);
if segment.get_joint_type() != JointType::NoJoint {
self.num_joints += 1;
self.locked_joints.push(false);
self.num_unlocked_joints += 1;
self.num_ind_joints = self.num_unlocked_joints;
self.coupling_matrix = DMatrix::identity(self.num_unlocked_joints, self.num_ind_joints);
}
}
pub fn add_chain(&mut self, mut chain: Chain) {
self.segments.append(&mut chain.segments);
self.num_joints += chain.num_joints;
}
pub fn get_segment(&self, index: usize) -> Segment {
self.segments[index]
}
pub fn get_locked_joints(&self) -> Vec<bool> {
self.locked_joints.clone()
}
pub fn set_coupling(
&mut self,
new_locked_joints: Vec<bool>,
new_coupling_matrix: DMatrix<f64>,
) {
let new_num_unlocked_joints = new_locked_joints.iter().filter(|&n| !(*n)).count();
if new_coupling_matrix.nrows() != new_num_unlocked_joints {
panic!(
"Wrong size of coupling arguments. Matrix has {} rows,
but the vector says there should be {}",
new_coupling_matrix.nrows(),
new_num_unlocked_joints
);
}
self.locked_joints = new_locked_joints;
self.num_unlocked_joints = new_num_unlocked_joints;
self.num_ind_joints = new_coupling_matrix.ncols();
self.coupling_matrix = new_coupling_matrix;
}
}
impl PartialEq for Chain {
fn eq(&self, other: &Self) -> bool {
(self.segments == other.segments)
&& (self.num_joints == other.num_joints)
&& (self.num_ind_joints == other.num_ind_joints)
&& (self.num_unlocked_joints == other.num_unlocked_joints)
&& (self.coupling_matrix == other.coupling_matrix)
}
}
#[cfg(test)]
pub mod tests {
use crate::chains::Chain;
use crate::geometry::{EulerBuild, Frame};
use crate::joint::{Joint, JointType};
use crate::segment::Segment;
pub fn create_testing_chain() -> Chain {
let mut chain = Chain::default();
chain.add_segment(Segment::new(
Joint::default().set_type(JointType::NoJoint),
Frame::from_translation_euler(0.1, -0.2, 0.3, -0.1, -0.2, 0.3),
0.0,
));
chain.add_segment(Segment::new(
Joint::default().set_type(JointType::RotZ),
Frame::from_translation_euler(0.2, 0.5, 0.1, 0.58, -1.2, 2.3),
0.0,
));
chain.add_segment(Segment::new(
Joint::default().set_type(JointType::RotZ),
Frame::from_translation_euler(0.02, 0.3, -0.81, 3.0, -1.7, 1.3),
0.0,
));
chain.add_segment(Segment::new(
Joint::default().set_type(JointType::RotZ),
Frame::from_translation_euler(0.4, -0.27, 0.19, 1.57, -1.57, 0.0),
0.0,
));
chain.add_segment(Segment::new(
Joint::default().set_type(JointType::RotZ),
Frame::from_translation_euler(0.24, -0.18, 0.16, 0.01, 0.0, -0.01),
0.0,
));
chain.add_segment(Segment::new(
Joint::default().set_type(JointType::RotZ),
Frame::from_translation_euler(1.0, -0.5, -0.01, 0.05, -1.02, 0.34),
0.0,
));
chain.add_segment(Segment::new(
Joint::default().set_type(JointType::RotZ),
Frame::from_translation_euler(0.02, 0.58, -0.87, 0.95, -1.74, 0.68),
0.0,
));
chain.add_segment(Segment::new(
Joint::default().set_type(JointType::RotZ),
Frame::from_translation_euler(0.2, 0.1, -0.1, -0.76, -0.94, 0.25),
0.0,
));
chain
}
}