ROBOOP, A Robotics Object Oriented Package in C++
controller.cpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2002-2004 Etienne Lachance
3 
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
8 
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13 
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 Report problems and direct all questions to:
20 
21 email: etienne.lachance@polymtl.ca or richard.gourdeau@polymtl.ca
22 
23 -------------------------------------------------------------------------------
24 Revision_history:
25 
26 2005/06/10: Etienne Lachance
27  -The desired joint acceleration was missing in the computed torque method.
28 
29 2005/11/06: Etienne Lachance
30  - No need to provide a copy constructor and the assignment operator
31  (operator=) for Impedance, Resolved_acc, Computed_torque_method and
32  Proportional_Derivative classes. Instead we use the one provide by the
33  compiler.
34 -------------------------------------------------------------------------------
35 */
36 
42 #include "controller.h"
43 
44 #ifdef use_namespace
45 namespace ROBOOP {
46  using namespace NEWMAT;
47 #endif
48 
49 
52 {
53  pc = ColumnVector(3); pc = 0;
54  pcp = pc;
55  pcpp = pc;
56  pcpp_prev = pc;
57  qc = Quaternion();
58  qcp = qc;
59  qcp_prev = qc;
60  quat = qc;
61  wc = pc;
62  wcp = pc;
63 }
64 
65 Impedance::Impedance(const Robot_basic & robot, const DiagonalMatrix & Mp_,
66  const DiagonalMatrix & Dp_, const DiagonalMatrix & Kp_,
67  const DiagonalMatrix & Mo_, const DiagonalMatrix & Do_,
68  const DiagonalMatrix & Ko_)
70 {
71  set_Mp(Mp_);
72  set_Dp(Dp_);
73  set_Kp(Kp_);
74  set_Mo(Mo_);
75  set_Do(Do_);
76  set_Ko(Ko_);
77 
78  pc = ColumnVector(3); pc = 0;
79  pcp = pc;
80  pcp_prev = pc;
81  pcpp = pc;
82  pcpp_prev = pc;
83  qc = Quaternion();
84  qcp = qc;
85  qcp_prev = qc;
86  quat = qc;
87  wc = pc;
88  wcp = pc;
89  wcp_prev = pc;
90 
91  Matrix Rot;
92  robot.kine(Rot, pc);
93  qc = Quaternion(Rot);
94 }
95 
96 short Impedance::set_Mp(const DiagonalMatrix & Mp_)
101 {
102  if(Mp_.Nrows() != 3)
103  {
104  Mp = DiagonalMatrix(3); Mp = 1;
105  cerr << "Impedance::set_Mp: wrong size for input matrix Mp" << endl;
106  return WRONG_SIZE;
107  }
108 
109  Mp = Mp_;
110  return 0;
111 }
112 
113 short Impedance::set_Mp(const Real Mp_i, const short i)
118 {
119  if( (i < 0) || (i > 3) )
120  {
121  cerr << "Impedance::set_Mp: index i out of bound" << endl;
122  return WRONG_SIZE;
123  }
124 
125  Mp(i) = Mp_i;
126  return 0;
127 }
128 
129 short Impedance::set_Dp(const DiagonalMatrix & Dp_)
134 {
135  if(Dp_.Nrows() != 3)
136  {
137  Dp = DiagonalMatrix(3); Dp = 1;
138  cerr << "Impedance::set_Dp: input matrix Dp of wrong size" << endl;
139  return WRONG_SIZE;
140  }
141 
142  Dp = Dp_;
143  return 0;
144 }
145 
146 short Impedance::set_Dp(const Real Dp_i, const short i)
151 {
152  if( (i < 0) || (i > 3) )
153  {
154  cerr << "Impedance::set_Dp: index i out of bound" << endl;
155  return WRONG_SIZE;
156  }
157 
158  Dp(i) = Dp_i;
159  return 0;
160 }
161 
162 short Impedance::set_Kp(const DiagonalMatrix & Kp_)
167 {
168  if(Kp_.Nrows() != 3)
169  {
170  Kp = DiagonalMatrix(3); Kp = 1;
171  cerr << "Impedance::set_Kp: wrong size for input matrix Kp" << endl;
172  return WRONG_SIZE;
173  }
174 
175  Kp = Kp_;
176  return 0;
177 }
178 
179 short Impedance::set_Kp(const Real Kp_i, const short i)
184 {
185  if( (i < 0) || (i > 3) )
186  {
187  cerr << "Impedance::set_Mp: index i out of bound" << endl;
188  return WRONG_SIZE;
189  }
190 
191  Kp(i) = Kp_i;
192  return 0;
193 }
194 
195 short Impedance::set_Mo(const DiagonalMatrix & Mo_)
200 {
201  if(Mo_.Nrows() != 3)
202  {
203  Mo = DiagonalMatrix(3); Mo = 1;
204  cerr << "Impedance::set_Mo: wrong size input matrix Mo" << endl;
205  return WRONG_SIZE;
206  }
207 
208  Mo = Mo_;
209  return 0;
210 }
211 
212 short Impedance::set_Mo(const Real Mo_i, const short i)
217 {
218  if( (i < 0) || (i > 3) )
219  {
220  cerr << "Impedance::set_Mo: index i out of bound" << endl;
221  return WRONG_SIZE;
222  }
223 
224  Mo(i) = Mo_i;
225  return 0;
226 }
227 
228 short Impedance::set_Do(const DiagonalMatrix & Do_)
233 {
234  if( Do_.Nrows() != 3)
235  {
236  Do = DiagonalMatrix(3); Do = 1;
237  cerr << "Impedance::set_Do: wrong size input matrix Do" << endl;
238  return WRONG_SIZE;
239  }
240 
241  Do = Do_;
242  return 0;
243 }
244 
245 short Impedance::set_Do(const Real Do_i, const short i)
250 {
251  if( (i < 0) || (i > 3) )
252  {
253  cerr << "Impedance::set_Do: index i out of bound" << endl;
254  return WRONG_SIZE;
255  }
256 
257  Do(i) = Do_i;
258  return 0;
259 }
260 
261 short Impedance::set_Ko(const DiagonalMatrix & Ko_)
266 {
267  if(Ko_.Nrows() != 3)
268  {
269  Ko = DiagonalMatrix(3); Ko = 1;
270  cerr << "Impedance::set_Ko: wrong size for input matrix Ko" << endl;
271  return WRONG_SIZE;
272  }
273 
274  Ko = Ko_;
275  return 0;
276 }
277 
278 short Impedance::set_Ko(const Real Ko_i, const short i)
283 {
284  if( (i < 0) || (i > 3) )
285  {
286  cerr << "Impedance::set_Ko: index i out of bound" << endl;
287  return WRONG_SIZE;
288  }
289 
290  Ko(i) = Ko_i;
291  return 0;
292 }
293 
294 short Impedance::control(const ColumnVector & pdpp, const ColumnVector & pdp,
295  const ColumnVector & pd, const ColumnVector & wdp,
296  const ColumnVector & wd, const Quaternion & qd,
297  const ColumnVector & f, const ColumnVector & n,
298  const Real dt)
324 {
325  if(pdpp.Nrows() !=3)
326  {
327  cerr << "Impedance::control: wrong size for input vector pdpp" << endl;
328  return WRONG_SIZE;
329  }
330  if(pdp.Nrows() !=3)
331  {
332  cerr << "Impedance::control: wrong size for input vector pdp" << endl;
333  return WRONG_SIZE;
334  }
335  if(pd.Nrows() != 3)
336  {
337  cerr << "Impedance::control: wrong size for input vector pd" << endl;
338  return WRONG_SIZE;
339  }
340  if(wdp.Nrows() !=3)
341  {
342  cerr << "Impedance::control: wrong size for input vector wdp" << endl;
343  return WRONG_SIZE;
344  }
345  if(wd.Nrows() !=3)
346  {
347  cerr << "Impedance::control: wrong size for input vector wd" << endl;
348  return WRONG_SIZE;
349  }
350  if(f.Nrows() !=3)
351  {
352  cerr << "Impedance::control: wrong size for input vector f" << endl;
353  return WRONG_SIZE;
354  }
355  if(n.Nrows() !=3)
356  {
357  cerr << "Impedance::control: wrong size for input vector f" << endl;
358  return WRONG_SIZE;
359  }
360 
361  static bool first=true;
362  if(first)
363  {
364  qc = qd;
365  qcp = qc.dot(wc, BASE_FRAME);
366  qcp_prev = qcp;
367  wc = wd;
368  wcp = wdp;
369  first = false;
370  }
371  if(qc.dot_prod(qd) < 0)
372  quat = qd*(-1);
373  else
374  quat = qd;
375 
376  qcd = quat * qc.i();
377 
378  // Solving pcpp, pcp, pc with the translational impedance
379  pcd = pc - pd;
380  pcdp = pcp - pdp;
381  // pcpp = pdpp + Mp.i()*(f - Dp*pcdp - Kp*pcd - 2*qcd.s()*Km.t()*qcd.v()); // (21)
382  pcpp = pdpp + Mp.i()*(f - Dp*pcdp - Kp*pcd);
383  pcp = pcp_prev + Integ_Trap(pcpp, pcpp_prev, dt);
384  pc = pc + Integ_Trap(pcp, pcp_prev, dt);
385 
386  // Solving wcp, wc, qc with the rotational impedance
387  wcd = wc - wd;
388  Ko_prime = 2*qcd.E(BASE_FRAME)*Ko; //(23)
389  // Km_prime = (qcd.s()*qcd.E(BASE_FRAME) - qcd.v()*qcd.v().t())*Km; // (24)
390  // wcp = wdp + Mo.i()*(n - Do*wcd - Ko_prime*qcd.v() - Km_prime*pcd); // (22)
391  wcp = wdp + Mo.i()*(n - Do*wcd - Ko_prime*qcd.v()); // (22)
392  wc = wc + Integ_Trap(wcp, wcp_prev, dt);
393  qcp = qc.dot(wc, BASE_FRAME);
394  Integ_quat(qcp, qcp_prev, qc, dt);
395 
396  return 0;
397 }
398 
399 // ------------------------------------------------------------------------------------------------------
400 // Position control based on resolved acceleration.
401 // ------------------------------------------------------------------------------------------------------
402 
405 {
406  Kvp = Kpp = Kvo = Kpo = 0;
407  zero3 = ColumnVector(3); zero3 = 0;
408  p = zero3;
409  pp = zero3;
410 
411  if(dof>0)
412  {
413  qp = ColumnVector(dof); qp = 0;
414  qpp = qp;
415  }
416 
417  quat_v_error = zero3;
418  a = ColumnVector(6); a = 0;
419  quat = Quaternion();
420 }
421 
423  const Real Kvp_,
424  const Real Kpp_,
425  const Real Kvo_,
426  const Real Kpo_)
428 {
429  set_Kvp(Kvp_);
430  set_Kpp(Kpp_);
431  set_Kvo(Kvo_);
432  set_Kpo(Kpo_);
433  zero3 = ColumnVector(3); zero3 = 0;
434  qp = ColumnVector(robot.get_dof()); qp = 0;
435  qpp = qp;
436  a = ColumnVector(6); a = 0;
437  p = zero3;
438  pp = zero3;
439  quat_v_error = zero3;
440  quat = Quaternion();
441 }
442 
443 void Resolved_acc::set_Kvp(const Real Kvp_)
445 {
446  Kvp = Kvp_;
447 }
448 
449 void Resolved_acc::set_Kpp(const Real Kpp_)
451 {
452  Kpp = Kpp_;
453 }
454 
455 void Resolved_acc::set_Kvo(const Real Kvo_)
457 {
458  Kvo = Kvo_;
459 }
460 
461 void Resolved_acc::set_Kpo(const Real Kpo_)
463 {
464  Kpo = Kpo_;
465 }
466 
467 ReturnMatrix Resolved_acc::torque_cmd(Robot_basic & robot, const ColumnVector & pdpp,
468  const ColumnVector & pdp, const ColumnVector & pd,
469  const ColumnVector & wdp, const ColumnVector & wd,
470  const Quaternion & quatd, const short link_pc,
471  const Real dt)
483 {
484  robot.kine_pd(Rot, p, pp, link_pc);
485 
486  Quaternion quate(Rot); // end effector orientation
487  if(quate.dot_prod(quatd) < 0)
488  quat = quatd*(-1);
489  else
490  quat = quatd;
491 
492  quat_v_error = quate.s()*quat.v() - quat.s()*quate.v() +
493  x_prod_matrix(quate.v())*quat.v();
494 
495  a.SubMatrix(1,3,1,1) = pdpp + Kvp*(pdp-pp) + Kpp*(pd-p);
496  a.SubMatrix(4,6,1,1) = wdp + Kvo*(wd-Rot*robot.w[robot.get_dof()]) +
497  Kpo*quat_v_error;
498  qp = robot.get_qp();
499  // (eps, lamda_max)
500  qpp = robot.jacobian_DLS_inv(0.015, 0.2)*(a - robot.jacobian_dot()*qp);
501  return robot.torque(robot.get_q(),qp, qpp, zero3, zero3);
502 }
503 
504 
505 // ------------------------------------------------------------------------------
506 // Position control based on Computed Torque Method
507 // ------------------------------------------------------------------------------
508 
511 {
512  dof = dof_;
513  qpp = ColumnVector(dof); qpp = 0;
514  q = qpp;
515  qp = qpp;
516  zero3 = ColumnVector(3); zero3 = 0;
517 }
518 
520  const DiagonalMatrix & Kp,
521  const DiagonalMatrix & Kd)
523 {
524  dof = robot.get_dof();
525  set_Kd(Kd);
526  set_Kp(Kp);
527  qpp = ColumnVector(dof); qpp = 0;
528  q = qpp;
529  qp = qpp;
530  zero3 = ColumnVector(3); zero3 = 0;
531 }
532 
534  const ColumnVector & qd,
535  const ColumnVector & qpd,
536  const ColumnVector & qppd )
538 {
539  if(qd.Nrows() != dof)
540  {
541  ColumnVector tau(dof); tau = 0;
542  cerr << "Computed_torque_methode::torque_cmd: wrong size for input vector qd" << endl;
543  tau.Release();
544  return tau;
545  }
546  if(qpd.Nrows() != dof)
547  {
548  ColumnVector tau(dof); tau = 0;
549  cerr << "Computed_torque_methode::torque_cmd: wrong size for input vector qpd" << endl;
550  tau.Release();
551  return tau;
552  }
553  if(qppd.Nrows() != dof)
554  {
555  ColumnVector tau(dof); tau = 0;
556  cerr << "Computed_torque_methode::torque_cmd: wrong size for input vector qppd" << endl;
557  tau.Release();
558  return tau;
559  }
560 
561  q = robot.get_q();
562  qp = robot.get_qp();
563  qpp = Kp*(qd-q) + Kd*(qpd-qp) + qppd;
564  return robot.torque(q, qp, qpp, zero3, zero3);
565 }
566 
567 short Computed_torque_method::set_Kd(const DiagonalMatrix & Kd_)
572 {
573  if(Kd_.Nrows() != dof)
574  {
575  Kd = DiagonalMatrix(dof); Kd = 0;
576  cerr << "Computed_torque_method::set_kd: wrong size for input matrix Kd." << endl;
577  return WRONG_SIZE;
578  }
579 
580  Kd = Kd_;
581  return 0;
582 }
583 
584 short Computed_torque_method::set_Kp(const DiagonalMatrix & Kp_)
589 {
590  if(Kp_.Nrows() != dof)
591  {
592  Kp = DiagonalMatrix(dof); Kp = 0;
593  cerr << "Computed_torque_method::set_kp: wrong size for input matrix Kp." << endl;
594  return WRONG_SIZE;
595  }
596 
597  Kp = Kp_;
598  return 0;
599 }
600 
601 // ------------------------------------------------------------------------------
602 // Position control based on Proportional_Derivative (PD)
603 // ------------------------------------------------------------------------------
604 
607 {
608  dof = dof_;
609  q = ColumnVector(dof); q = 0;
610  qp = q;
611  zero3 = ColumnVector(3); zero3 = 0;
612 }
613 
615  const DiagonalMatrix & Kp,
616  const DiagonalMatrix & Kd)
618 {
619  dof = robot.get_dof();
620  set_Kp(Kp);
621  set_Kd(Kd);
622  q = ColumnVector(dof); q = 0;
623  qp = q;
624  tau = ColumnVector(dof); tau = 0;
625  zero3 = ColumnVector(3); zero3 = 0;
626 }
627 
629  const ColumnVector & qd,
630  const ColumnVector & qpd)
632 {
633  if(qd.Nrows() != dof)
634  {
635  tau = 0;
636  cerr << "Proportional_Derivative::torque_cmd: wrong size for input vector qd" << endl;
637  return tau;
638  }
639  if(qpd.Nrows() != dof)
640  {
641  tau = 0;
642  cerr << "Proportional_Derivative::torque_cmd: wrong size for input vector qpd" << endl;
643  return tau;
644  }
645 
646  q = robot.get_q();
647  qp = robot.get_qp();
648  tau = Kp*(qd-q) + Kd*(qpd-qp);
649 
650  return tau;
651 }
652 
653 short Proportional_Derivative::set_Kd(const DiagonalMatrix & Kd_)
658 {
659  if(Kd_.Nrows() != dof)
660  {
661  Kd = DiagonalMatrix(dof); Kd = 0;
662  cerr << "Proportional_Derivative::set_kd: wrong size for input matrix Kd." << endl;
663  return WRONG_SIZE;
664  }
665 
666  Kd = Kd_;
667  return 0;
668 }
669 
670 short Proportional_Derivative::set_Kp(const DiagonalMatrix & Kp_)
675 {
676  if(Kp_.Nrows() != dof)
677  {
678  Kp = DiagonalMatrix(dof); Kp = 0;
679  cerr << "Computed_torque_method::set_kp: wrong size for input matrix Kp." << endl;
680  return WRONG_SIZE;
681  }
682 
683  Kp = Kp_;
684  return 0;
685 }
686 
687 #ifdef use_namespace
688 }
689 #endif