1use crate::KidyChain;
2use liealg::{prelude::*, se3};
3use nalgebra::{Matrix6, Vector3, Vector6};
4
5impl<const N: usize> KidyChain<N> {
6 pub fn id(
8 &self,
9 theta: [f64; N],
10 dtheta: [f64; N],
11 ddtheta: [f64; N],
12 gravity: [f64; 3],
13 f_tip: se3<f64>,
14 ) -> [f64; N] {
15 let mut twists = vec![se3::new([0.0, 0.0, 0.0], [0.0, 0.0, 0.0]); N + 1];
16 let mut dtwists = vec![se3::new([0.0, 0.0, 0.0], [0.0, 0.0, 0.0]); N + 1];
17
18 let g = se3::new([0.0, 0.0, 0.0], gravity);
20 dtwists[0] = g;
21
22 for i in 1..N + 1 {
24 let t = (self.local_screw[i - 1].clone() * -theta[i - 1]).exp()
26 * self.local_zero_pose[i].clone().inv();
27
28 let v =
30 t.adjoint().act(&twists[i - 1]) + self.local_screw[i - 1].clone() * dtheta[i - 1];
31 twists[i] = v.clone();
32
33 let dv = t.adjoint().act(&dtwists[i - 1])
35 + ad_mul_se(ad(&v), &self.local_screw[i - 1]) * dtheta[i - 1]
36 + self.local_screw[i - 1].clone() * ddtheta[i - 1];
37 dtwists[i] = dv;
38 }
39
40 let mut wrenchs = vec![se3::new([0.0, 0.0, 0.0], [0.0, 0.0, 0.0]); N + 1];
41 wrenchs[N] = f_tip;
42 let mut tau = [0.0; N];
43 for i in (1..N + 1).rev() {
44 let t = (self.local_screw[i].clone() * -theta[i - 1]).exp()
45 * self.local_zero_pose[i + 1].clone().inv();
46 wrenchs[i] = t.adjoint().transpose().act(&wrenchs[i + 1])
47 + inertial_mul_se3(self.local_spatial_inertial[i], &dtwists[i])
48 - ad_mul_se(ad(&twists[i]).transpose(), &twists[i]);
49 tau[i - 1] = cross_se3(&wrenchs[i], &self.local_screw[i - 1]);
50 }
51 tau
52 }
53
54 pub fn fd(&self) {
56 println!("KidyChain fd");
57 }
58}
59
60fn ad(v: &se3<f64>) -> Matrix6<f64> {
61 let v = v.vee().as_array();
62 let p = Vector3::new(v[0], v[1], v[2]);
63 let w = Vector3::new(v[3], v[4], v[5]);
64 let a = liealg::hat(&p);
65 let b = liealg::hat(&w);
66 let mut res = Matrix6::zeros();
67 res.view_mut((0, 0), (3, 3)).copy_from(&a);
68 res.view_mut((3, 3), (3, 3)).copy_from(&a);
69 res.view_mut((3, 0), (3, 3)).copy_from(&b);
70 res
71}
72
73fn ad_mul_se(m: Matrix6<f64>, w: &se3<f64>) -> se3<f64> {
74 let vec6 = Vector6::from_column_slice(w.vee().as_slice());
75 let res = m * vec6;
76 se3::new([res[0], res[1], res[2]], [res[3], res[4], res[5]])
77}
78
79fn inertial_mul_se3(g: Matrix6<f64>, v: &se3<f64>) -> se3<f64> {
80 let vec6 = Vector6::from_column_slice(v.vee().as_slice());
81 let res = g * vec6;
82 se3::new([res[0], res[1], res[2]], [res[3], res[4], res[5]])
83}
84
85fn cross_se3(v: &se3<f64>, w: &se3<f64>) -> f64 {
86 let vec_v = Vector6::from_column_slice(v.vee().as_slice());
87 let vec_w = Vector6::from_column_slice(w.vee().as_slice());
88 vec_v.dot(&vec_w)
89}
90
91#[cfg(test)]
92mod test {
93 #[test]
96 fn test_ad() {
97 }
101}