phyicubhelpers.h
1 /********************************************************************************
2  * WorldSim -- library for robot simulations *
3  * Copyright (C) 2008-2011 Gianluca Massera <emmegian@yahoo.it> *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the Free Software *
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
18  ********************************************************************************/
19 
20 #ifdef FARSA_USE_YARP_AND_ICUB
21 
22 #ifndef PHYICUBHELPERS_H
23 #define PHYICUBHELPERS_H
24 
25 #include "worldsimconfig.h"
26 #include "wvector.h"
27 #include "wmatrix.h"
28 #include "wquaternion.h"
29 #include "world.h"
30 #include "yarpobject.h"
31 #include "wmesh.h"
32 #include "phyhinge.h"
33 #include "phyobject.h"
34 #include <QVector>
35 #include <QSet>
36 #include <QMap>
37 #include <QString>
38 #include <string>
39 #include <typeinfo>
40 
41 // All this stuff is to get rid of annoying warnings...
42 #ifdef __GNUC__
43 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
44 #pragma GCC diagnostic push
45 #pragma GCC diagnostic ignored "-Wunused-parameter"
46 #else
47 #pragma GCC diagnostic ignored "-Wunused-parameter"
48 #endif
49 #endif
50  #include "yarp/dev/CartesianControl.h"
51  #include "yarp/os/ConnectionReader.h"
52  #include "yarp/os/PortReader.h"
53  #include "iCub/iKin/iKinHlp.h"
54  #include "iCub/iKin/iKinSlv.h"
55 #ifdef __GNUC__
56 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
57 #pragma GCC diagnostic pop
58 #else
59 #pragma GCC diagnostic warning "-Wunused-parameter"
60 #endif
61 #endif
62 
63 namespace farsa {
64  class PhyiCub;
65 
73  FARSA_WSIM_API std::ostream& operator<<(std::ostream &os, const wMatrix &m);
74 
82  FARSA_WSIM_API std::ostream& operator<<(std::ostream &os, const wVector &v);
83 
90  FARSA_WSIM_API void convertYarpMatrixToWorldMatrix(const yarp::sig::Matrix &y, wMatrix &w);
91 
98  FARSA_WSIM_API void convertWorldMatrixToYarpMatrix(const wMatrix &w, yarp::sig::Matrix &y);
99 
106  class FARSA_WSIM_API DOFStatusListener : public QObject
107  {
108  Q_OBJECT
109 
110  public:
121  DOFStatusListener(const PhyDOF* dof, Qt::ConnectionType connType = Qt::DirectConnection);
122 
127 
135  void update();
136 
142  real position() const
143  {
144  return m_curPosition;
145  }
146 
147  private slots:
153  void setLinkAngle(real newAngle);
154 
160  void setDesideredPosition(real desideredAngle);
161 
168  void setDesideredVelocity(real velocity);
169 
170  protected:
174  const PhyDOF* const m_dof;
175 
183 
188 
193 
201  };
202 
229  class FARSA_WSIM_API PhyObjectsGroup : public WObject
230  {
231  Q_OBJECT
232 
233  public:
237  typedef int ChainIDType;
238 
245  typedef int ElementIDType;
246 
247  public:
255  PhyObjectsGroup(PhyObject* headObject, World* world, QString name = "unamed");
256 
260  ~PhyObjectsGroup();
261 
270  ElementIDType addObject(PhyObject* obj, ChainIDType chainID = ChainIDType());
271 
282  ElementIDType addJointDOF(PhyJoint* joint, unsigned int dofID, ChainIDType chainID = ChainIDType());
283 
292  void setKinematic(bool b);
293 
301  void setStatic(bool b);
302 
310  void enableJoints(bool b);
311 
318  void updateRelativePositions();
319 
324  void resetObjectPositions()
325  {
326  changedMatrix();
327  }
328 
355  void setDOFPosition(real pos, ChainIDType chainID, ElementIDType dof);
356 
363  void updateFromDOF();
364 
370  virtual void preUpdate();
371 
377  virtual void postUpdate();
378 
384  PhyObject* getHeadObject() const
385  {
386  return m_headObject;
387  }
388 
389  private:
396  virtual void changedMatrix();
397 
401  PhyObject *const m_headObject;
402 
407  struct ObjectAndMatrix
408  {
409  ObjectAndMatrix() :
410  object(NULL),
411  matrix()
412  {
413  }
414 
415  ObjectAndMatrix(PhyObject* obj, wMatrix mtr) :
416  object(obj),
417  matrix(mtr)
418  {
419  }
420 
421  PhyObject* object;
422  wMatrix matrix;
423  };
424 
431  QMap<ChainIDType, QVector<ObjectAndMatrix> > m_objects;
432 
437  struct DOFAndListener
438  {
439  DOFAndListener() :
440  joint(NULL),
441  dofID(0),
442  listener(NULL)
443  {
444  }
445 
446  DOFAndListener(PhyJoint* j, unsigned int d, DOFStatusListener* l) :
447  joint(j),
448  dofID(d),
449  listener(l)
450  {
451  }
452 
453  PhyJoint* joint;
454  unsigned int dofID;
455  DOFStatusListener* listener;
456  };
457 
464  QMap<ChainIDType, QVector<DOFAndListener> > m_joints;
465  };
466 
515  class FARSA_WSIM_API KinematicLinkInfo : public QObject
516  {
517  Q_OBJECT
518 
519  public:
530 
543  KinematicLinkInfo(iCub::iKin::iKinLimb* chain, unsigned int linkID);
544 
550  KinematicLinkInfo(const KinematicLinkInfo& other);
551 
557  KinematicLinkInfo& operator=(const KinematicLinkInfo& other);
558 
562  virtual ~KinematicLinkInfo();
563 
571  void setBuddies(QSet<KinematicLinkInfo*> buddies);
572 
580  void setWObject(WObject* wObject, const wMatrix &m = s_identityMatrix);
581 
587  WObject* getWObject() const
588  {
589  return m_wObject;
590  }
591 
599  const wMatrix& getWObjectMatrix() const
600  {
601  return m_objectMatrix;
602  }
603 
612  const wVector& getAxis() const
613  {
614  return m_axis;
615  }
616 
625  wVector getAxisWorld() const
626  {
627  return m_worldTm->rotateVector(m_axis);
628  }
629 
641  const wVector& getBottom() const
642  {
643  return m_bottom;
644  }
645 
656  wVector getBottomWorld() const
657  {
658  return m_worldTm->transformVector(m_bottom);
659  }
660 
669  const wVector& getTop() const
670  {
671  return m_top;
672  }
673 
682  wVector getTopWorld() const
683  {
684  return m_worldTm->transformVector(m_top);
685  }
686 
694  real getHeight() const
695  {
696  return m_height;
697  }
698 
706  const wVector& getRotAxis() const
707  {
708  return m_rotAxis;
709  }
710 
718  wVector getRotAxisWObject() const
719  {
720  return m_objectMatrix.unrotateVector(m_rotAxis);
721  }
722 
732  const wVector& getRotCenter() const
733  {
734  return m_rotCenter;
735  }
736 
746  wVector getRotCenterWObject() const
747  {
748  return m_objectMatrix.untransformVector(m_rotCenter);
749  }
750 
763  void setWorldMatrix(const wMatrix *mtr);
764 
774  const wMatrix& getWorldMatrix() const
775  {
776  return *m_worldTm;
777  }
778 
786  yarp::sig::Matrix getYarpMatrix() const
787  {
788  return m_chain->getH(m_linkID, true);
789  }
790 
799  wMatrix getYarpMatrixAswMatrix() const
800  {
801  wMatrix mtr;
802  convertYarpMatrixToWorldMatrix(m_chain->getH(m_linkID, true), mtr);
803  return mtr;
804  }
805 
812  const iCub::iKin::iKinLink& getiKinLink() const
813  {
814  return (*(m_chain->asChain()))[m_linkID];
815  }
816 
823  void updateInformationFromiKin();
824 
829  void updateMatrixFromiKin();
830 
846  void setJoint(PhyJoint *joint, bool invertedJointAxis = true, unsigned int dof = 0, bool doConnection = true, Qt::ConnectionType connType = Qt::DirectConnection);
847 
853  PhyJoint* getJoint() const
854  {
855  return m_phyJoint;
856  }
857 
863  unsigned int getJointDOF() const
864  {
865  return m_phyJointDOF;
866  }
867 
868  public slots:
874  void setLinkAngle(real newAngle);
875 
881  void setDesideredPosition(real desideredAngle);
882 
889  void setDesideredVelocity(real velocity);
890 
897  void setiKinLinkLimits(real min, real max);
898 
905  void updateLink();
906 
907  private:
917  void setWObject_NB(WObject* wObject, const wMatrix &m = s_identityMatrix);
918 
928  void setWorldMatrix_NB(const wMatrix *mtr);
929 
936  void updateInformationFromiKin_NB();
937 
945  void updateMatrixFromiKin_NB();
946 
964  void setJoint_NB(PhyJoint *joint, bool invertedJointAxis = true, unsigned int dof = 0, bool doConnection = true, Qt::ConnectionType connType = Qt::DirectConnection);
965 
973  void setLinkAngle_NB(real newAngle);
974 
982  void setDesideredPosition_NB(real desideredAngle);
983 
992  void setDesideredVelocity_NB(real velocity);
993 
1002  void setiKinLinkLimits_NB(real min, real max);
1003 
1010  void updateLink_NB();
1011 
1018  mutable QSet<KinematicLinkInfo*> m_buddies;
1019 
1031  bool m_isMasterBuddy;
1032 
1036  iCub::iKin::iKinLimb* m_chain;
1037 
1041  unsigned int m_linkID;
1042 
1046  WObject* m_wObject;
1047 
1052  wMatrix m_objectMatrix;
1053 
1061  wVector m_axis;
1062 
1072  wVector m_bottom;
1073 
1081  wVector m_top;
1082 
1089  real m_height;
1090 
1095  wVector m_rotAxis;
1096 
1104  wVector m_rotCenter;
1105 
1113  const wMatrix* m_worldTm;
1114 
1120  PhyJoint* m_phyJoint;
1121 
1125  unsigned int m_phyJointDOF;
1126 
1131  bool m_invertedJointAxis;
1132 
1136  real m_nextAngle;
1137 
1141  real m_velocity;
1142 
1149  PhyDOF::MotionMode m_motionMode;
1150 
1155  bool m_linkAngleUpdated;
1156 
1161  static const wMatrix s_identityMatrix;
1162  };
1163 
1175  template <class iKinLimb_t>
1176  class FARSA_WSIM_TEMPLATE KinematicLimb : public iKinLimb_t
1177  {
1178  public:
1182  typedef iKinLimb_t iKinLimb;
1183 
1184  public:
1189  iKinLimb(),
1190  m_links(),
1191  m_rootObject(NULL)
1192  {
1193  initLinkInfoList();
1194  }
1195 
1204  KinematicLimb(const std::string &type) :
1205  iKinLimb(type),
1206  m_links(),
1207  m_rootObject(NULL)
1208  {
1209  initLinkInfoList();
1210  }
1211 
1216  {
1217  }
1218 
1226  const KinematicLinkInfo& getLinkInfo(int i) const
1227  {
1228  return m_links[i];
1229  }
1230 
1238  KinematicLinkInfo& getLinkInfo(int i)
1239  {
1240  return m_links[i];
1241  }
1242 
1252  void setWorldMatrix(const wMatrix *mtr)
1253  {
1254  for (int i = 0; i < m_links.size(); i++) {
1255  m_links[i].setWorldMatrix(mtr);
1256  }
1257  }
1258 
1268  const wMatrix& getWorldMatrix() const
1269  {
1270  return m_links[0].getWorldMatrix();
1271  }
1272 
1279  void updateInformationFromiKin()
1280  {
1281  for (int i = 0; i < m_links.size(); i++) {
1282  m_links[i].updateInformationFromiKin();
1283  }
1284  }
1285 
1304  void updateMatrixFromiKin(int updateObjMatrixFromLink = 0, int updateObjMatrixUpToLink = -1)
1305  {
1306  if (updateObjMatrixFromLink < 0) {
1307  updateObjMatrixFromLink = 0;
1308  }
1309  if ((updateObjMatrixUpToLink < 0) || (updateObjMatrixUpToLink >= m_links.size())) {
1310  updateObjMatrixUpToLink = m_links.size() - 1;
1311  }
1312  // Updating links
1313  //for (int i = 0; i < m_links.size(); i++) {
1314  for (int i = updateObjMatrixFromLink; i <= updateObjMatrixUpToLink; i++) {
1315  m_links[i].updateLink();
1316  }
1317 
1318  // Now updating matrices
1319  for (int i = updateObjMatrixFromLink; i <= updateObjMatrixUpToLink; i++) {
1320  m_links[i].updateMatrixFromiKin();
1321  }
1322  }
1323 
1332  void setRootObject(WObject* rootObject)
1333  {
1334  m_rootObject = rootObject;
1335  }
1336 
1342  WObject* getRootObject() const
1343  {
1344  return m_rootObject;
1345  }
1346 
1370  PhyJoint* createJoint(int linkID, bool invertAxis = true, bool doConnection = true, Qt::ConnectionType connType = Qt::DirectConnection, unsigned int dof = 0)
1371  {
1372  // First getting axis and objects
1373  const wVector axis = invertAxis ? -getLinkInfo(linkID).getRotAxisWObject() : getLinkInfo(linkID).getRotAxisWObject();
1374  PhyObject* parent = dynamic_cast<PhyObject*>(getLinkInfo(linkID).getWObject());
1375  if (parent == NULL) {
1376  // Let's try to convert to PhyObjectsGroup
1377  PhyObjectsGroup* grp = dynamic_cast<PhyObjectsGroup*>(getLinkInfo(linkID).getWObject());
1378  if (grp != NULL) {
1379  // If we can convert parent object to PhyObjectsGroup, we use its head object
1380  parent = grp->getHeadObject();
1381  }
1382  }
1383  WObject* const childWObject = (linkID <= 0) ? m_rootObject : getLinkInfo(linkID - 1).getWObject();
1384  PhyObject* child = dynamic_cast<PhyObject*>(childWObject);
1385  if ((child == NULL) && (typeid(childWObject) == typeid(PhyObjectsGroup*))) {
1386  // If we can convert child object to PhyObjectsGroup, we use its head object
1387  child = (dynamic_cast<PhyObjectsGroup*>(childWObject))->getHeadObject();
1388  }
1389 
1390  Q_ASSERT_X((parent != NULL), "PhyObjectsGroup::createJoint", "This is going to crash, parent object in joint is NULL");
1391 
1392  // Now creating joint and putting it in the link info object
1393  PhyJoint* joint = new PhyHinge(axis, getLinkInfo(linkID).getRotCenterWObject(), parent, child);
1394  getLinkInfo(linkID).setJoint(joint, invertAxis, dof, doConnection, connType);
1395 
1396  return joint;
1397  }
1398 
1399  private:
1403  void initLinkInfoList()
1404  {
1405  // Adding all links
1406  for (unsigned int i = 0; i < this->getN(); i++) {
1407  m_links.push_back(KinematicLinkInfo(this, i));
1408  this->releaseLink(i); // We always work as if all links are released
1409  }
1410  }
1411 
1415  QVector<KinematicLinkInfo> m_links;
1416 
1424  WObject *m_rootObject;
1425  };
1426 } // end namespace farsa
1427 
1428 #endif
1429 
1430 #endif // FARSA_USE_YARP_AND_ICUB