Skip to main content

ik_geo/inverse_kinematics/hardcoded/
setups.rs

1use {
2    super::{
3        irb6640, kuka_r800_fixed_q3, rrc_fixed_q6, spherical_bot, three_parallel_bot,
4        two_parallel_bot, ur5, yumi_fixed_q3,
5    },
6    crate::{
7        inverse_kinematics::{
8            auxiliary::{Kinematics, Matrix3x7, Matrix3x8},
9            setups::{calculate_ik_error, ik_write_output, SetupIk},
10        },
11        subproblems::{auxiliary::random_angle, setups::SetupStatic, Vector7},
12    },
13    nalgebra::{Matrix3, Matrix3x6, Vector3, Vector6},
14    std::f64::{consts::PI, NAN},
15};
16
17macro_rules! define_struct {
18    ($name:ident, $num_joints:expr) => {
19        pub struct $name {
20            kin: Kinematics<$num_joints, { $num_joints + 1 }>,
21            r: Matrix3<f64>,
22            t: Vector3<f64>,
23
24            q: Vec<Vector6<f64>>,
25            is_ls: Vec<bool>,
26        }
27    };
28}
29
30// Define all structures
31define_struct!(Irb6640, 6);
32define_struct!(KukaR800FixedQ3, 7);
33define_struct!(RrcFixedQ6, 7);
34define_struct!(YumiFixedQ3, 7);
35define_struct!(Ur5, 6);
36define_struct!(ThreeParallelBot, 6);
37define_struct!(TwoParallelBot, 6);
38define_struct!(SphericalBot, 6);
39
40pub fn hardcoded_setup_from_string(raw: &str, r: &mut Matrix3<f64>, t: &mut Vector3<f64>) {
41    let data: Vec<f64> = raw.split(',').map(|s| s.parse().unwrap()).collect();
42
43    *r = Matrix3::new(
44        data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
45    );
46
47    *t = Vector3::new(data[9], data[10], data[11]);
48}
49
50impl Irb6640 {
51    pub fn get_kin() -> Kinematics<6, 7> {
52        let mut kin = Kinematics::new();
53
54        let zv = Vector3::zeros();
55        let ex = Vector3::x();
56        let ey = Vector3::y();
57        let ez = Vector3::z();
58
59        kin.h = Matrix3x6::from_columns(&[ez, ey, ey, ex, ey, ex]);
60        kin.p = Matrix3x7::from_columns(&[
61            zv,
62            0.32 * ex + 0.78 * ez,
63            1.075 * ez,
64            1.1425 * ex + 0.2 * ez,
65            zv,
66            zv,
67            0.2 * ex,
68        ]);
69
70        kin
71    }
72}
73
74impl KukaR800FixedQ3 {
75    const Q3: f64 = PI / 6.0;
76
77    pub fn get_kin() -> Kinematics<7, 8> {
78        let mut kin = Kinematics::new();
79
80        let zv = Vector3::zeros();
81        let ey = Vector3::y();
82        let ez = Vector3::z();
83
84        kin.h = Matrix3x7::from_columns(&[ez, ey, ez, -ey, ez, ey, ez]);
85        kin.p = Matrix3x8::from_columns(&[
86            (0.15 + 0.19) * ez,
87            zv,
88            0.21 * ez,
89            0.19 * ez,
90            (0.21 + 0.19) * ez,
91            zv,
92            zv,
93            (0.081 + 0.045) * ez,
94        ]);
95
96        kin
97    }
98
99    pub fn get_kin_partial() -> (Kinematics<6, 7>, Matrix3<f64>) {
100        let kin = Self::get_kin();
101        kin.forward_kinematics_partial(Self::Q3, 2, &Matrix3::identity())
102    }
103}
104
105impl RrcFixedQ6 {
106    const Q6: f64 = PI / 6.0;
107
108    pub fn get_kin() -> Kinematics<7, 8> {
109        let mut kin = Kinematics::new();
110
111        let zv = Vector3::zeros();
112        let ex = Vector3::x();
113        let ey = Vector3::y();
114        let ez = Vector3::z();
115
116        let p01 = zv;
117        let p12 = 20.0 * ex - 4.0 * ey;
118        let p23 = 4.0 * ey;
119        let p34 = 21.5 * ex + 3.375 * ey;
120        let p45 = -3.375 * ey;
121        let p56 = 21.5 * ex + 3.325 * ey;
122        let p67 = -3.325 * ey;
123        let p7t = 7.0 * ex;
124
125        kin.p = 0.0254 * Matrix3x8::from_columns(&[p01, p12, p23, p34, p45, p56, p67, p7t]);
126        kin.h = Matrix3x7::from_columns(&[ex, ez, ex, ez, ex, ez, ex]);
127
128        kin
129    }
130
131    pub fn get_kin_partial() -> (Kinematics<6, 7>, Matrix3<f64>) {
132        let kin = Self::get_kin();
133        let (mut kin_partial, r_6t) =
134            kin.forward_kinematics_partial(Self::Q6, 5, &Matrix3::identity());
135
136        let zv = Vector3::zeros();
137        let alpha = (kin_partial.h.fixed_columns::<2>(4))
138            .pseudo_inverse(1e-12)
139            .unwrap()
140            * kin_partial.p.column(5);
141        let delta_p_45 = alpha[0] * kin_partial.h.column(4);
142        let delta_p_6t = alpha[1] * kin_partial.h.column(5);
143
144        kin_partial
145            .p
146            .set_column(4, &(kin_partial.p.column(4) + delta_p_45));
147        kin_partial.p.set_column(5, &zv);
148        kin_partial
149            .p
150            .set_column(6, &(kin_partial.p.column(6) + delta_p_6t));
151
152        (kin_partial, r_6t)
153    }
154}
155
156impl YumiFixedQ3 {
157    const Q3: f64 = PI / 6.0;
158
159    pub fn get_kin() -> Kinematics<7, 8> {
160        let mut kin = Kinematics::new();
161
162        kin.p = Matrix3x8::from_row_slice(&[
163            0.0536, 0.0642, 0.1578, 0.0880, 0.1270, 0.0354, 0.0385, 0.0040, 0.0725, 0.0527, 0.0406,
164            0.0011, -0.0877, -0.0712, -0.0087, -0.0043, 0.4149, 0.0632, 0.0650, 0.0143, -0.0700,
165            -0.0670, -0.0030, -0.0038,
166        ]);
167
168        kin.h = Matrix3x7::from_row_slice(&[
169            0.8138, 0.1048, 0.8138, 0.1048, 0.5716, 0.1048, 0.5716, 0.3420, 0.7088, 0.3420, 0.7088,
170            -0.6170, 0.7088, -0.6170, 0.4698, -0.6976, 0.4698, -0.6976, -0.5410, -0.6976, -0.5410,
171        ]);
172
173        for i in 0..kin.h.ncols() {
174            kin.h.set_column(i, &kin.h.column(i).normalize());
175        }
176
177        kin
178    }
179
180    pub fn get_kin_partial() -> (Kinematics<6, 7>, Matrix3<f64>) {
181        let kin = Self::get_kin();
182        kin.forward_kinematics_partial(Self::Q3, 2, &Matrix3::identity())
183    }
184}
185
186impl Ur5 {
187    pub fn get_kin() -> Kinematics<6, 7> {
188        let mut kin = Kinematics::new();
189
190        let ex = Vector3::x();
191        let ey = Vector3::y();
192        let ez = Vector3::z();
193
194        kin.h = Matrix3x6::from_columns(&[ez, ey, ey, ey, -ez, ey]);
195        kin.p = Matrix3x7::from_columns(&[
196            0.089159 * ez,
197            0.1358 * ey,
198            -0.1197 * ey + 0.425 * ex,
199            0.3922 * ex,
200            0.093 * ey,
201            -0.0946 * ez,
202            0.0823 * ey,
203        ]);
204
205        kin
206    }
207}
208
209impl ThreeParallelBot {
210    pub fn get_kin() -> Kinematics<6, 7> {
211        let mut kin = Kinematics::new();
212
213        let ex = Vector3::x();
214        let ey = Vector3::y();
215        let ez = Vector3::z();
216
217        kin.h = Matrix3x6::from_columns(&[ez, ex, ex, ex, ez, ex]);
218        kin.p = Matrix3x7::from_columns(&[ez, ey, ey, ey, ey, ey + ex, ex]);
219
220        kin
221    }
222}
223
224impl TwoParallelBot {
225    pub fn get_kin() -> Kinematics<6, 7> {
226        let mut kin = Kinematics::new();
227
228        let ex = Vector3::x();
229        let ey = Vector3::y();
230        let ez = Vector3::z();
231
232        let es = (ex + ez).normalize();
233
234        kin.h = Matrix3x6::from_columns(&[ez, ex, ex, ez, ex, es]);
235        kin.p = Matrix3x7::from_columns(&[ez, ey, ey, ey, ey, ey, ez]);
236
237        kin
238    }
239}
240
241impl SphericalBot {
242    pub fn get_kin() -> Kinematics<6, 7> {
243        let mut kin = Kinematics::new();
244
245        let zv = Vector3::zeros();
246        let ex = Vector3::x();
247        let ey = Vector3::y();
248        let ez = Vector3::z();
249
250        kin.h = Matrix3x6::from_columns(&[ey, ez, ey, ex, ey, ex]);
251        kin.p = Matrix3x7::from_columns(&[zv, ez + ex, ez + ex, ez + ex, zv, zv, ex]);
252
253        kin
254    }
255}
256
257// Most of the implementations in SetupIk are the same, so we can use a macro to generate them.
258macro_rules! impl_setup_ik {
259    // Generate the function setup_from_str, write_output,ls_count, solution_count, name, and debug
260    ($name:ident) => {
261        fn setup_from_str(&mut self, raw: &str) {
262            hardcoded_setup_from_string(raw, &mut self.r, &mut self.t);
263        }
264
265        fn write_output(&self) -> String {
266            ik_write_output(&self.q)
267        }
268
269        fn ls_count(&self) -> usize {
270            self.is_ls.iter().filter(|b| **b).count()
271        }
272
273        fn solution_count(&self) -> usize {
274            self.is_ls.len()
275        }
276
277        fn name(&self) -> &'static str {
278            <$name as SetupStatic>::name()
279        }
280
281        fn debug(&self, i: usize) {
282            println!("{i}{}{}", self.r, self.t);
283        }
284    };
285}
286
287impl SetupIk for Irb6640 {
288    fn setup(&mut self) {
289        let q = Vector6::zeros().map(|_: f64| random_angle());
290        (self.r, self.t) = self.kin.forward_kinematics(&q);
291    }
292
293    impl_setup_ik!(Irb6640);
294
295    fn run(&mut self) {
296        (self.q, self.is_ls) = irb6640(&self.r, &self.t)
297    }
298
299    fn error(&self) -> f64 {
300        self.q
301            .iter()
302            .map(|q| calculate_ik_error(&self.kin, &self.r, &self.t, q))
303            .reduce(f64::min)
304            .unwrap_or(NAN)
305    }
306}
307
308impl SetupIk for KukaR800FixedQ3 {
309    fn setup(&mut self) {
310        let mut q = Vector7::zeros().map(|_: f64| random_angle());
311        q[2] = Self::Q3;
312        (self.r, self.t) = self.kin.forward_kinematics(&q);
313    }
314
315    impl_setup_ik!(KukaR800FixedQ3);
316
317    fn run(&mut self) {
318        (self.q, self.is_ls) = kuka_r800_fixed_q3(&self.r, &self.t);
319    }
320
321    fn error(&self) -> f64 {
322        self.q
323            .iter()
324            .map(|q| {
325                let q_e =
326                    Vector7::from_column_slice(&[q[0], q[1], Self::Q3, q[2], q[3], q[4], q[5]]);
327
328                let (r_t, t_t) = self.kin.forward_kinematics(&q_e);
329                (r_t - self.r).norm() + (t_t - self.t).norm()
330            })
331            .reduce(f64::min)
332            .unwrap_or(NAN)
333    }
334}
335
336impl SetupIk for RrcFixedQ6 {
337    fn setup(&mut self) {
338        let mut q = Vector7::zeros().map(|_: f64| random_angle());
339        q[5] = Self::Q6;
340        (self.r, self.t) = self.kin.forward_kinematics(&q);
341    }
342
343    impl_setup_ik!(RrcFixedQ6);
344
345    fn run(&mut self) {
346        (self.q, self.is_ls) = rrc_fixed_q6(&self.r, &self.t);
347    }
348
349    fn error(&self) -> f64 {
350        self.q
351            .iter()
352            .map(|q| {
353                let q_e =
354                    Vector7::from_column_slice(&[q[0], q[1], q[2], q[3], q[4], Self::Q6, q[5]]);
355
356                let (r_t, t_t) = self.kin.forward_kinematics(&q_e);
357                (r_t - self.r).norm() + (t_t - self.t).norm()
358            })
359            .reduce(f64::min)
360            .unwrap_or(NAN)
361    }
362}
363
364impl SetupIk for YumiFixedQ3 {
365    fn setup(&mut self) {
366        let mut q = Vector7::zeros().map(|_: f64| random_angle());
367        q[2] = Self::Q3;
368        (self.r, self.t) = self.kin.forward_kinematics(&q);
369    }
370
371    impl_setup_ik!(YumiFixedQ3);
372
373    fn run(&mut self) {
374        (self.q, self.is_ls) = yumi_fixed_q3(&self.r, &self.t);
375    }
376
377    fn error(&self) -> f64 {
378        self.q
379            .iter()
380            .map(|q| {
381                let q_e =
382                    Vector7::from_column_slice(&[q[0], q[1], Self::Q3, q[2], q[3], q[4], q[5]]);
383
384                let (r_t, t_t) = self.kin.forward_kinematics(&q_e);
385                (r_t - self.r).norm() + (t_t - self.t).norm()
386            })
387            .reduce(f64::min)
388            .unwrap_or(NAN)
389    }
390}
391
392impl SetupIk for Ur5 {
393    fn setup(&mut self) {
394        let q = Vector6::zeros().map(|_: f64| random_angle());
395        (self.r, self.t) = self.kin.forward_kinematics(&q);
396    }
397
398    impl_setup_ik!(Ur5);
399
400    fn run(&mut self) {
401        (self.q, self.is_ls) = ur5(&self.r, &self.t);
402    }
403
404    fn error(&self) -> f64 {
405        self.q
406            .iter()
407            .map(|q| calculate_ik_error(&self.kin, &self.r, &self.t, q))
408            .reduce(f64::min)
409            .unwrap_or(NAN)
410    }
411}
412
413impl SetupIk for ThreeParallelBot {
414    fn setup(&mut self) {
415        let q = Vector6::zeros().map(|_: f64| random_angle());
416        (self.r, self.t) = self.kin.forward_kinematics(&q);
417    }
418
419    impl_setup_ik!(ThreeParallelBot);
420
421    fn run(&mut self) {
422        (self.q, self.is_ls) = three_parallel_bot(&self.r, &self.t);
423    }
424
425    fn error(&self) -> f64 {
426        self.q
427            .iter()
428            .map(|q| calculate_ik_error(&self.kin, &self.r, &self.t, q))
429            .reduce(f64::min)
430            .unwrap_or(NAN)
431    }
432}
433
434impl SetupIk for TwoParallelBot {
435    fn setup(&mut self) {
436        let q = Vector6::zeros().map(|_: f64| random_angle());
437        (self.r, self.t) = self.kin.forward_kinematics(&q);
438    }
439
440    impl_setup_ik!(TwoParallelBot);
441
442    fn run(&mut self) {
443        (self.q, self.is_ls) = two_parallel_bot(&self.r, &self.t);
444    }
445
446    fn error(&self) -> f64 {
447        self.q
448            .iter()
449            .map(|q| calculate_ik_error(&self.kin, &self.r, &self.t, q))
450            .reduce(f64::min)
451            .unwrap_or(NAN)
452    }
453}
454
455impl SetupIk for SphericalBot {
456    fn setup(&mut self) {
457        let q = Vector6::zeros().map(|_: f64| random_angle());
458        (self.r, self.t) = self.kin.forward_kinematics(&q);
459    }
460
461    impl_setup_ik!(SphericalBot);
462
463    fn run(&mut self) {
464        (self.q, self.is_ls) = spherical_bot(&self.r, &self.t);
465    }
466
467    fn error(&self) -> f64 {
468        self.q
469            .iter()
470            .map(|q| calculate_ik_error(&self.kin, &self.r, &self.t, q))
471            .reduce(f64::min)
472            .unwrap_or(NAN)
473    }
474}
475
476// Do setup static as a macro to avoid repition
477macro_rules! impl_setup_static {
478    ($name:ident, $long_name:expr) => {
479        impl SetupStatic for $name {
480            fn new() -> Self {
481                Self {
482                    kin: Self::get_kin(),
483                    r: Matrix3::zeros(),
484                    t: Vector3::zeros(),
485
486                    q: Vec::new(),
487                    is_ls: Vec::new(),
488                }
489            }
490
491            fn name() -> &'static str {
492                $long_name
493            }
494        }
495    };
496}
497
498// Implement static setup for all the robots
499impl_setup_static!(Irb6640, "IRB 6640");
500impl_setup_static!(KukaR800FixedQ3, "KUKA R800 Fixed Q3");
501impl_setup_static!(RrcFixedQ6, "RRC Fixed Q6");
502impl_setup_static!(YumiFixedQ3, "Yumi Fixed Q3");
503impl_setup_static!(Ur5, "UR5");
504impl_setup_static!(ThreeParallelBot, "Three Parallel Bot");
505impl_setup_static!(TwoParallelBot, "Two Parallel Bot");
506impl_setup_static!(SphericalBot, "Spherical Bot");