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
30define_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
257macro_rules! impl_setup_ik {
259 ($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
476macro_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
498impl_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");