worldsim/include/phyicubhelpers.h

00001 /********************************************************************************
00002  *  WorldSim -- library for robot simulations                                   *
00003  *  Copyright (C) 2008-2011 Gianluca Massera <emmegian@yahoo.it>                *
00004  *                                                                              *
00005  *  This program is free software; you can redistribute it and/or modify        *
00006  *  it under the terms of the GNU General Public License as published by        *
00007  *  the Free Software Foundation; either version 2 of the License, or           *
00008  *  (at your option) any later version.                                         *
00009  *                                                                              *
00010  *  This program is distributed in the hope that it will be useful,             *
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of              *
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               *
00013  *  GNU General Public License for more details.                                *
00014  *                                                                              *
00015  *  You should have received a copy of the GNU General Public License           *
00016  *  along with this program; if not, write to the Free Software                 *
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA  *
00018  ********************************************************************************/
00019 
00020 #ifdef FARSA_USE_YARP_AND_ICUB
00021 
00022 #ifndef PHYICUBHELPERS_H
00023 #define PHYICUBHELPERS_H
00024 
00025 #include "worldsimconfig.h"
00026 #include "wvector.h"
00027 #include "wmatrix.h"
00028 #include "wquaternion.h"
00029 #include "world.h"
00030 #include "yarpobject.h"
00031 #include "wmesh.h"
00032 #include "phyhinge.h"
00033 #include "phyobject.h"
00034 #include <QVector>
00035 #include <QSet>
00036 #include <QMap>
00037 #include <QString>
00038 #include <string>
00039 #include <typeinfo>
00040 
00041 // All this stuff is to get rid of annoying warnings...
00042 #ifdef __GNUC__
00043 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
00044 #pragma GCC diagnostic push
00045 #pragma GCC diagnostic ignored "-Wunused-parameter"
00046 #else
00047 #pragma GCC diagnostic ignored "-Wunused-parameter"
00048 #endif
00049 #endif
00050     #include "yarp/dev/CartesianControl.h"
00051     #include "yarp/os/ConnectionReader.h"
00052     #include "yarp/os/PortReader.h"
00053     #include "iCub/iKin/iKinHlp.h"
00054     #include "iCub/iKin/iKinSlv.h"
00055 #ifdef __GNUC__
00056 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5)
00057 #pragma GCC diagnostic pop
00058 #else
00059 #pragma GCC diagnostic warning "-Wunused-parameter"
00060 #endif
00061 #endif
00062 
00063 namespace farsa {
00064     class PhyiCub;
00065 
00073     FARSA_WSIM_API std::ostream& operator<<(std::ostream &os, const wMatrix &m);
00074 
00082     FARSA_WSIM_API std::ostream& operator<<(std::ostream &os, const wVector &v);
00083 
00090     FARSA_WSIM_API void convertYarpMatrixToWorldMatrix(const yarp::sig::Matrix &y, wMatrix &w);
00091 
00098     FARSA_WSIM_API void convertWorldMatrixToYarpMatrix(const wMatrix &w, yarp::sig::Matrix &y);
00099 
00106     class FARSA_WSIM_API DOFStatusListener : public QObject
00107     {
00108         Q_OBJECT
00109 
00110     public:
00121         DOFStatusListener(const PhyDOF* dof, Qt::ConnectionType connType = Qt::DirectConnection);
00122 
00126         ~DOFStatusListener();
00127 
00135         void update();
00136 
00142         real position() const
00143         {
00144             return m_curPosition;
00145         }
00146 
00147     private slots:
00153         void setLinkAngle(real newAngle);
00154 
00160         void setDesideredPosition(real desideredAngle);
00161 
00168         void setDesideredVelocity(real velocity);
00169 
00170     protected:
00174         const PhyDOF* const m_dof;
00175 
00182         real m_curPosition;
00183 
00187         real m_desideredPosition;
00188 
00192         real m_velocity;
00193 
00200         PhyDOF::MotionMode m_motionMode;
00201     };
00202 
00229     class FARSA_WSIM_API PhyObjectsGroup : public WObject
00230     {
00231         Q_OBJECT
00232 
00233     public:
00237         typedef int ChainIDType;
00238 
00245         typedef int ElementIDType;
00246 
00247     public:
00255         PhyObjectsGroup(PhyObject* headObject, World* world, QString name = "unamed");
00256 
00260         ~PhyObjectsGroup();
00261 
00270         ElementIDType addObject(PhyObject* obj, ChainIDType chainID = ChainIDType());
00271 
00282         ElementIDType addJointDOF(PhyJoint* joint, unsigned int dofID, ChainIDType chainID = ChainIDType());
00283 
00292         void setKinematic(bool b);
00293 
00301         void setStatic(bool b);
00302 
00310         void enableJoints(bool b);
00311 
00318         void updateRelativePositions();
00319 
00324         void resetObjectPositions()
00325         {
00326             changedMatrix();
00327         }
00328 
00355         void setDOFPosition(real pos, ChainIDType chainID, ElementIDType dof);
00356 
00363         void updateFromDOF();
00364 
00370         virtual void preUpdate();
00371 
00377         virtual void postUpdate();
00378 
00384         PhyObject* getHeadObject() const
00385         {
00386             return m_headObject;
00387         }
00388 
00389     private:
00396         virtual void changedMatrix();
00397 
00401         PhyObject *const m_headObject;
00402 
00407         struct ObjectAndMatrix
00408         {
00409             ObjectAndMatrix() :
00410                 object(NULL),
00411                 matrix()
00412             {
00413             }
00414 
00415             ObjectAndMatrix(PhyObject* obj, wMatrix mtr) :
00416                 object(obj),
00417                 matrix(mtr)
00418             {
00419             }
00420 
00421             PhyObject* object;
00422             wMatrix matrix;
00423         };
00424 
00431         QMap<ChainIDType, QVector<ObjectAndMatrix> > m_objects;
00432 
00437         struct DOFAndListener
00438         {
00439             DOFAndListener() :
00440                 joint(NULL),
00441                 dofID(0),
00442                 listener(NULL)
00443             {
00444             }
00445 
00446             DOFAndListener(PhyJoint* j, unsigned int d, DOFStatusListener* l) :
00447                 joint(j),
00448                 dofID(d),
00449                 listener(l)
00450             {
00451             }
00452 
00453             PhyJoint* joint;
00454             unsigned int dofID;
00455             DOFStatusListener* listener;
00456         };
00457 
00464         QMap<ChainIDType, QVector<DOFAndListener> > m_joints;
00465     };
00466 
00515     class FARSA_WSIM_API KinematicLinkInfo : public QObject
00516     {
00517         Q_OBJECT
00518 
00519     public:
00529         KinematicLinkInfo();
00530 
00543         KinematicLinkInfo(iCub::iKin::iKinLimb* chain, unsigned int linkID);
00544 
00550         KinematicLinkInfo(const KinematicLinkInfo& other);
00551 
00557         KinematicLinkInfo& operator=(const KinematicLinkInfo& other);
00558 
00562         virtual ~KinematicLinkInfo();
00563 
00571         void setBuddies(QSet<KinematicLinkInfo*> buddies);
00572 
00580         void setWObject(WObject* wObject, const wMatrix &m = s_identityMatrix);
00581 
00587         WObject* getWObject() const
00588         {
00589             return m_wObject;
00590         }
00591 
00599         const wMatrix& getWObjectMatrix() const
00600         {
00601             return m_objectMatrix;
00602         }
00603 
00612         const wVector& getAxis() const
00613         {
00614             return m_axis;
00615         }
00616 
00625         wVector getAxisWorld() const
00626         {
00627             return m_worldTm->rotateVector(m_axis);
00628         }
00629 
00641         const wVector& getBottom() const
00642         {
00643             return m_bottom;
00644         }
00645 
00656         wVector getBottomWorld() const
00657         {
00658             return m_worldTm->transformVector(m_bottom);
00659         }
00660 
00669         const wVector& getTop() const
00670         {
00671             return m_top;
00672         }
00673 
00682         wVector getTopWorld() const
00683         {
00684             return m_worldTm->transformVector(m_top);
00685         }
00686 
00694         real getHeight() const
00695         {
00696             return m_height;
00697         }
00698 
00706         const wVector& getRotAxis() const
00707         {
00708             return m_rotAxis;
00709         }
00710 
00718         wVector getRotAxisWObject() const
00719         {
00720             return m_objectMatrix.unrotateVector(m_rotAxis);
00721         }
00722 
00732         const wVector& getRotCenter() const
00733         {
00734             return m_rotCenter;
00735         }
00736 
00746         wVector getRotCenterWObject() const
00747         {
00748             return m_objectMatrix.untransformVector(m_rotCenter);
00749         }
00750 
00763         void setWorldMatrix(const wMatrix *mtr);
00764 
00774         const wMatrix& getWorldMatrix() const
00775         {
00776             return *m_worldTm;
00777         }
00778 
00786         yarp::sig::Matrix getYarpMatrix() const
00787         {
00788             return m_chain->getH(m_linkID, true);
00789         }
00790 
00799         wMatrix getYarpMatrixAswMatrix() const
00800         {
00801             wMatrix mtr;
00802             convertYarpMatrixToWorldMatrix(m_chain->getH(m_linkID, true), mtr);
00803             return mtr;
00804         }
00805 
00812         const iCub::iKin::iKinLink& getiKinLink() const
00813         {
00814             return (*(m_chain->asChain()))[m_linkID];
00815         }
00816 
00823         void updateInformationFromiKin();
00824 
00829         void updateMatrixFromiKin();
00830 
00846         void setJoint(PhyJoint *joint, bool invertedJointAxis = true, unsigned int dof = 0, bool doConnection = true, Qt::ConnectionType connType = Qt::DirectConnection);
00847 
00853         PhyJoint* getJoint() const
00854         {
00855             return m_phyJoint;
00856         }
00857 
00863         unsigned int getJointDOF() const
00864         {
00865             return m_phyJointDOF;
00866         }
00867 
00868     public slots:
00874         void setLinkAngle(real newAngle);
00875 
00881         void setDesideredPosition(real desideredAngle);
00882 
00889         void setDesideredVelocity(real velocity);
00890 
00897         void setiKinLinkLimits(real min, real max);
00898 
00905         void updateLink();
00906 
00907     private:
00917         void setWObject_NB(WObject* wObject, const wMatrix &m = s_identityMatrix);
00918 
00928         void setWorldMatrix_NB(const wMatrix *mtr);
00929 
00936         void updateInformationFromiKin_NB();
00937 
00945         void updateMatrixFromiKin_NB();
00946 
00964         void setJoint_NB(PhyJoint *joint, bool invertedJointAxis = true, unsigned int dof = 0, bool doConnection = true, Qt::ConnectionType connType = Qt::DirectConnection);
00965 
00973         void setLinkAngle_NB(real newAngle);
00974 
00982         void setDesideredPosition_NB(real desideredAngle);
00983 
00992         void setDesideredVelocity_NB(real velocity);
00993 
01002         void setiKinLinkLimits_NB(real min, real max);
01003 
01010         void updateLink_NB();
01011 
01018         mutable QSet<KinematicLinkInfo*> m_buddies;
01019 
01031         bool m_isMasterBuddy;
01032 
01036         iCub::iKin::iKinLimb* m_chain;
01037 
01041         unsigned int m_linkID;
01042 
01046         WObject* m_wObject;
01047 
01052         wMatrix m_objectMatrix;
01053 
01061         wVector m_axis;
01062 
01072         wVector m_bottom;
01073 
01081         wVector m_top;
01082 
01089         real m_height;
01090 
01095         wVector m_rotAxis;
01096 
01104         wVector m_rotCenter;
01105 
01113         const wMatrix* m_worldTm;
01114 
01120         PhyJoint* m_phyJoint;
01121 
01125         unsigned int m_phyJointDOF;
01126 
01131         bool m_invertedJointAxis;
01132 
01136         real m_nextAngle;
01137 
01141         real m_velocity;
01142 
01149         PhyDOF::MotionMode m_motionMode;
01150 
01155         bool m_linkAngleUpdated;
01156 
01161         static const wMatrix s_identityMatrix;
01162     };
01163 
01175     template <class iKinLimb_t>
01176     class FARSA_WSIM_TEMPLATE KinematicLimb : public iKinLimb_t
01177     {
01178     public:
01182         typedef iKinLimb_t iKinLimb;
01183 
01184     public:
01188         KinematicLimb() :
01189             iKinLimb(),
01190             m_links(),
01191             m_rootObject(NULL)
01192         {
01193             initLinkInfoList();
01194         }
01195 
01204         KinematicLimb(const std::string &type) :
01205             iKinLimb(type),
01206             m_links(),
01207             m_rootObject(NULL)
01208         {
01209             initLinkInfoList();
01210         }
01211 
01215         ~KinematicLimb()
01216         {
01217         }
01218 
01226         const KinematicLinkInfo& getLinkInfo(int i) const
01227         {
01228             return m_links[i];
01229         }
01230 
01238         KinematicLinkInfo& getLinkInfo(int i)
01239         {
01240             return m_links[i];
01241         }
01242 
01252         void setWorldMatrix(const wMatrix *mtr)
01253         {
01254             for (int i = 0; i < m_links.size(); i++) {
01255                 m_links[i].setWorldMatrix(mtr);
01256             }
01257         }
01258 
01268         const wMatrix& getWorldMatrix() const
01269         {
01270             return m_links[0].getWorldMatrix();
01271         }
01272 
01279         void updateInformationFromiKin()
01280         {
01281             for (int i = 0; i < m_links.size(); i++) {
01282                 m_links[i].updateInformationFromiKin();
01283             }
01284         }
01285 
01304         void updateMatrixFromiKin(int updateObjMatrixFromLink = 0, int updateObjMatrixUpToLink = -1)
01305         {
01306             if (updateObjMatrixFromLink < 0) {
01307                 updateObjMatrixFromLink = 0;
01308             }
01309             if ((updateObjMatrixUpToLink < 0) || (updateObjMatrixUpToLink >= m_links.size())) {
01310                 updateObjMatrixUpToLink = m_links.size() - 1;
01311             }
01312             // Updating links
01313             //for (int i = 0; i < m_links.size(); i++) {
01314             for (int i = updateObjMatrixFromLink; i <= updateObjMatrixUpToLink; i++) {
01315                 m_links[i].updateLink();
01316             }
01317 
01318             // Now updating matrices
01319             for (int i = updateObjMatrixFromLink; i <= updateObjMatrixUpToLink; i++) {
01320                 m_links[i].updateMatrixFromiKin();
01321             }
01322         }
01323 
01332         void setRootObject(WObject* rootObject)
01333         {
01334             m_rootObject = rootObject;
01335         }
01336 
01342         WObject* getRootObject() const
01343         {
01344             return m_rootObject;
01345         }
01346 
01370         PhyJoint* createJoint(int linkID, bool invertAxis = true, bool doConnection = true, Qt::ConnectionType connType = Qt::DirectConnection, unsigned int dof = 0)
01371         {
01372             // First getting axis and objects
01373             const wVector axis = invertAxis ? -getLinkInfo(linkID).getRotAxisWObject() : getLinkInfo(linkID).getRotAxisWObject();
01374             PhyObject* parent = dynamic_cast<PhyObject*>(getLinkInfo(linkID).getWObject());
01375             if (parent == NULL) {
01376                 // Let's try to convert to PhyObjectsGroup
01377                 PhyObjectsGroup* grp = dynamic_cast<PhyObjectsGroup*>(getLinkInfo(linkID).getWObject());
01378                 if (grp != NULL) {
01379                     // If we can convert parent object to PhyObjectsGroup, we use its head object
01380                     parent = grp->getHeadObject();
01381                 }
01382             }
01383             WObject* const childWObject = (linkID <= 0) ? m_rootObject : getLinkInfo(linkID - 1).getWObject();
01384             PhyObject* child = dynamic_cast<PhyObject*>(childWObject);
01385             if ((child == NULL) && (typeid(childWObject) == typeid(PhyObjectsGroup*))) {
01386                 // If we can convert child object to PhyObjectsGroup, we use its head object
01387                 child = (dynamic_cast<PhyObjectsGroup*>(childWObject))->getHeadObject();
01388             }
01389 
01390             Q_ASSERT_X((parent != NULL), "PhyObjectsGroup::createJoint", "This is going to crash, parent object in joint is NULL");
01391 
01392             // Now creating joint and putting it in the link info object
01393             PhyJoint* joint = new PhyHinge(axis, getLinkInfo(linkID).getRotCenterWObject(), parent, child);
01394             getLinkInfo(linkID).setJoint(joint, invertAxis, dof, doConnection, connType);
01395 
01396             return joint;
01397         }
01398 
01399     private:
01403         void initLinkInfoList()
01404         {
01405             // Adding all links
01406             for (unsigned int i = 0; i < this->getN(); i++) {
01407                 m_links.push_back(KinematicLinkInfo(this, i));
01408                 this->releaseLink(i); // We always work as if all links are released
01409             }
01410         }
01411 
01415         QVector<KinematicLinkInfo> m_links;
01416 
01424         WObject *m_rootObject;
01425     };
01426 } // end namespace farsa
01427 
01428 #endif
01429 
01430 #endif // FARSA_USE_YARP_AND_ICUB