worldsim/src/phyicubhelpers.cpp

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 #ifdef __GNUC__
00023     #warning ================================================================================================================================================================================================================= PENSARE A DIVIDERE wVector IN UNA CLASSE PER I VETTORI (QUARTO ELEMENTO = 0) E UNA PER I PUNTI (QUARTO ELEMENTO = 1) =================================================================================================================================================================================================================
00024 #endif
00025 
00026 #include "phyicubhelpers.h"
00027 #include "phyicub.h"
00028 #include "phybox.h"
00029 #include "phycylinder.h"
00030 #include "physphere.h"
00031 #include "phyfixed.h"
00032 #include "phyhinge.h"
00033 #include "phyuniversal.h"
00034 #include "phycompoundobject.h"
00035 #include "motorcontrollers.h"
00036 #include "wcamera.h"
00037 
00038 #ifdef __GNUC__
00039 #pragma GCC diagnostic ignored "-Wunused-parameter"
00040 #endif
00041     #include "yarp/os/ResourceFinder.h"
00042     #include "yarp/os/Bottle.h"
00043     #include "yarp/os/Property.h"
00044     #include "yarp/dev/PolyDriverList.h"
00045     #include "yarp/dev/Wrapper.h"
00046     #include "yarp/os/RateThread.h"
00047     #include "yarp/os/Network.h"
00048 #ifdef __GNUC__
00049 #pragma GCC diagnostic warning "-Wunused-parameter"
00050 #endif
00051 
00052 using namespace yarp::os;
00053 using namespace yarp::dev;
00054 using namespace iCub::iKin;
00055 
00056 #include <iostream>
00057 
00058 namespace farsa {
00059     // Perhaps we should move this function and the next one into wMatrix.h and wVector.h
00060     std::ostream& operator<<(std::ostream &os, const wMatrix &m)
00061     {
00062         os.precision(3);
00063         os.setf(std::ostream::fixed);
00064         os.unsetf(std::ostream::scientific);
00065         os << std::endl
00066            << "\t" << m[0][0] << "\t" << m[0][1] << "\t" << m[0][2] << "\t" << m[0][3] << std::endl
00067            << "\t" << m[1][0] << "\t" << m[1][1] << "\t" << m[1][2] << "\t" << m[1][3] << std::endl
00068            << "\t" << m[2][0] << "\t" << m[2][1] << "\t" << m[2][2] << "\t" << m[2][3] << std::endl
00069            << "\t" << m[3][0] << "\t" << m[3][1] << "\t" << m[3][2] << "\t" << m[3][3] << std::endl;
00070 
00071         return os;
00072     }
00073 
00074     std::ostream& operator<<(std::ostream &os, const wVector &v)
00075     {
00076         os.precision(3);
00077         os.setf(std::ostream::fixed);
00078         os.unsetf(std::ostream::scientific);
00079         os << "[" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << "]";
00080 
00081         return os;
00082     }
00083 
00084     void convertYarpMatrixToWorldMatrix(const yarp::sig::Matrix &y, wMatrix &w)
00085     {
00086         // Extremely ugly, but works for sure... Yarp matrix are in conventional
00087         // order, wMatrix are like openGL matrices
00088         w[0][0] = y[0][0];
00089         w[0][1] = y[1][0];
00090         w[0][2] = y[2][0];
00091         w[0][3] = y[3][0];
00092         w[1][0] = y[0][1];
00093         w[1][1] = y[1][1];
00094         w[1][2] = y[2][1];
00095         w[1][3] = y[3][1];
00096         w[2][0] = y[0][2];
00097         w[2][1] = y[1][2];
00098         w[2][2] = y[2][2];
00099         w[2][3] = y[3][2];
00100         w[3][0] = y[0][3];
00101         w[3][1] = y[1][3];
00102         w[3][2] = y[2][3];
00103         w[3][3] = y[3][3];
00104     }
00105 
00106     void convertWorldMatrixToYarpMatrix(const wMatrix &w, yarp::sig::Matrix &y)
00107     {
00108         // Extremely ugly, but works for sure... Yarp matrix are in conventional
00109         // order, wMatrix are like openGL matrices
00110         y[0][0] = w[0][0];
00111         y[0][1] = w[1][0];
00112         y[0][2] = w[2][0];
00113         y[0][3] = w[3][0];
00114         y[1][0] = w[0][1];
00115         y[1][1] = w[1][1];
00116         y[1][2] = w[2][1];
00117         y[1][3] = w[3][1];
00118         y[2][0] = w[0][2];
00119         y[2][1] = w[1][2];
00120         y[2][2] = w[2][2];
00121         y[2][3] = w[3][2];
00122         y[3][0] = w[0][3];
00123         y[3][1] = w[1][3];
00124         y[3][2] = w[2][3];
00125         y[3][3] = w[3][3];
00126     }
00127 
00128     DOFStatusListener::DOFStatusListener(const PhyDOF* dof, Qt::ConnectionType connType) :
00129         QObject(NULL),
00130         m_dof(dof),
00131         m_curPosition(dof->position()),
00132         m_desideredPosition(dof->desiredPosition()),
00133         m_velocity(dof->desiredVelocity()),
00134         m_motionMode(dof->motion())
00135     {
00136         // Connecting our slots to those of the PhyDOF object
00137         connect(m_dof, SIGNAL(changedPosition(real)), this, SLOT(setLinkAngle(real)), connType);
00138         connect(m_dof, SIGNAL(changedDesiredPosition(real)), this, SLOT(setDesideredPosition(real)), connType);
00139         connect(m_dof, SIGNAL(changedDesiredVelocity(real)), this, SLOT(setDesideredVelocity(real)), connType);
00140     }
00141 
00142     DOFStatusListener::~DOFStatusListener()
00143     {
00144         // Nothing to do here
00145     }
00146 
00147     void DOFStatusListener::update()
00148     {
00149         switch (m_motionMode) {
00150             case PhyDOF::force:
00151                 {
00152                     // Not supported (never will)
00153                 }
00154                 break;
00155             case PhyDOF::vel:
00156                 {
00157                     // When setting the new position we also have to check limits here (ramp simply
00158                     // clamps the position within limits)
00159                     real lowLimit, highLimit;
00160                     m_dof->limits(lowLimit, highLimit);
00161                     m_curPosition = ramp(lowLimit, highLimit, m_curPosition + m_velocity * m_dof->joint()->world()->timeStep());
00162                     m_motionMode = PhyDOF::off;
00163                 }
00164                 break;
00165             case PhyDOF::pos:
00166                 {
00167                     m_curPosition = m_desideredPosition;
00168                     m_motionMode = PhyDOF::off;
00169                 }
00170                 break;
00171             case PhyDOF::off:
00172                 {
00173                     // Nothing to do, here
00174                 }
00175                 break;
00176         }
00177     }
00178 
00179     void DOFStatusListener::setLinkAngle(real newAngle)
00180     {
00181         m_curPosition = newAngle;
00182     }
00183 
00184     void DOFStatusListener::setDesideredPosition(real desideredAngle)
00185     {
00186         m_desideredPosition = desideredAngle;
00187         m_motionMode = PhyDOF::pos;
00188     }
00189 
00190     void DOFStatusListener::setDesideredVelocity(real velocity)
00191     {
00192         m_velocity = velocity;
00193         m_motionMode = PhyDOF::vel;
00194     }
00195 
00196     PhyObjectsGroup::PhyObjectsGroup(PhyObject* headObject, World* world, QString name) :
00197         WObject(world, name),
00198         m_headObject(headObject),
00199         m_objects(),
00200         m_joints()
00201     {
00202         // Setting the transformation matrix equal to the object matrix
00203         tm = m_headObject->matrix();
00204     }
00205 
00206     PhyObjectsGroup::~PhyObjectsGroup()
00207     {
00208         // Deleting all joint listeners
00209         for (QMap<ChainIDType, QVector<DOFAndListener> >::iterator it = m_joints.begin(); it != m_joints.end(); it++) {
00210             for (int i = 0; i < it.value().size(); i++) {
00211                 delete it.value()[i].listener;
00212             }
00213         }
00214     }
00215 
00216     PhyObjectsGroup::ElementIDType PhyObjectsGroup::addObject(PhyObject* obj, PhyObjectsGroup::ChainIDType chainID)
00217     {
00218         // Storing matrix for the object relative to the head object frame of reference
00219         wMatrix invHeadMatrix = m_headObject->matrix().inverse();
00220         m_objects[chainID].push_back(ObjectAndMatrix(obj, obj->matrix() * invHeadMatrix));
00221 
00222         return (m_objects[chainID].size() - 1);
00223     }
00224 
00225     PhyObjectsGroup::ElementIDType PhyObjectsGroup::addJointDOF(PhyJoint* joint, unsigned int dofID, PhyObjectsGroup::ChainIDType chainID)
00226     {
00227         Q_ASSERT_X(joint->numDofs() > dofID, "PhyObjectsGroup::addJointDOF", "Joint has not the given dof");
00228         m_joints[chainID].push_back(DOFAndListener(joint, dofID, new DOFStatusListener(joint->dofs()[0])));
00229 
00230         return (m_joints[chainID].size() - 1);
00231     }
00232 
00233     void PhyObjectsGroup::setKinematic(bool b)
00234     {
00235         // Calling setKinematic on all objects
00236         m_headObject->setKinematic(b);
00237         for (QMap<ChainIDType, QVector<ObjectAndMatrix> >::iterator it = m_objects.begin(); it != m_objects.end(); it++) {
00238             for (int i = 0; i < it.value().size(); i++) {
00239                 it.value()[i].object->setKinematic(b);
00240             }
00241         }
00242     }
00243 
00244     void PhyObjectsGroup::setStatic(bool b)
00245     {
00246         // Calling setStatic on all objects
00247         m_headObject->setStatic(b);
00248         for (QMap<ChainIDType, QVector<ObjectAndMatrix> >::iterator it = m_objects.begin(); it != m_objects.end(); it++) {
00249             for (int i = 0; i < it.value().size(); i++) {
00250                 it.value()[i].object->setStatic(b);
00251             }
00252         }
00253     }
00254 
00255     void PhyObjectsGroup::enableJoints(bool b)
00256     {
00257         // Calling enable on all joints
00258         for (QMap<ChainIDType, QVector<DOFAndListener> >::iterator it = m_joints.begin(); it != m_joints.end(); it++) {
00259             for (int i = 0; i < it.value().size(); i++) {
00260                 it.value()[i].joint->enable(b);
00261             }
00262         }
00263     }
00264 
00265     void PhyObjectsGroup::updateRelativePositions()
00266     {
00267         // Storing matrix for all objects relative to the head object frame of reference
00268         wMatrix invHeadMatrix = m_headObject->matrix().inverse();
00269         for (QMap<ChainIDType, QVector<ObjectAndMatrix> >::iterator it = m_objects.begin(); it != m_objects.end(); it++) {
00270             for (int i = 0; i < it.value().size(); i++) {
00271                 it.value()[i].matrix = it.value()[i].object->matrix() * invHeadMatrix;
00272             }
00273         }
00274     }
00275 
00276     void PhyObjectsGroup::setDOFPosition(real pos, PhyObjectsGroup::ChainIDType chainID, PhyObjectsGroup::ElementIDType dof)
00277     {
00278         // First checking the joint and its child object exist (these are all asserts for performance reasons)
00279         Q_ASSERT_X(m_joints.contains(chainID), "PhyObjectsGroup::setDOFPosition", "No joint chain with the given ID");
00280         Q_ASSERT_X(m_joints[chainID].size() > dof, "PhyObjectsGroup::setDOFPosition", "No joint with the given ID in the given chain");
00281         Q_ASSERT_X(m_joints[chainID][dof].joint->dofs()[m_joints[chainID][dof].dofID]->rotate(), "PhyObjectsGroup::setDOFPosition", "Linear joints are not supported");
00282         Q_ASSERT_X(m_objects.contains(chainID), "PhyObjectsGroup::setDOFPosition", "No object chain with the given ID");
00283         Q_ASSERT_X(m_objects[chainID].size() > dof, "PhyObjectsGroup::setDOFPosition", "No object with the given ID in the given chain");
00284 
00285         QVector<ObjectAndMatrix>& objChain = m_objects[chainID];
00286         QVector<DOFAndListener>& jointChain = m_joints[chainID];
00287         PhyDOF* phydof = jointChain[dof].joint->dofs()[m_joints[chainID][dof].dofID];
00288 
00289         // Computing the new matrix relative to the head object for all elements after the given joint
00290         for (ElementIDType i = dof; i < objChain.size(); i++) {
00291             const wMatrix newMatrixWorldCoordinate = objChain[i].object->matrix().rotateAround(-phydof->axis(), phydof->centre(), pos - phydof->position());
00292             objChain[i].matrix = newMatrixWorldCoordinate * matrix().inverse();
00293         }
00294 
00295         // Also updating joint and moving object (first objects, then joints because joints
00296         // need both the parent and the child in the correct position)
00297         for (ElementIDType i = dof; i < objChain.size(); i++) {
00298             objChain[i].object->setMatrix(objChain[i].matrix * matrix());
00299         }
00300         for (ElementIDType i = dof; i < jointChain.size(); i++) {
00301             jointChain[i].joint->updateJointInfo();
00302         }
00303     }
00304 
00305     void PhyObjectsGroup::updateFromDOF()
00306     {
00307         // This could be made a bit more efficient if there was a function like setDOFPosition
00308         // taking pointer to objects instead of their indexes. However most of the work is in
00309         // computing matrix multiplication, so for the moment it is ok this way
00310 
00311         // Here we simply cycle through the list dofs for each kinematic chain and call setDOFPosition
00312         for (QMap<ChainIDType, QVector<DOFAndListener> >::iterator it = m_joints.begin(); it != m_joints.end(); it++) {
00313             for (int i = 0; i < it.value().size(); i++) {
00314                 it.value()[i].listener->update();
00315                 setDOFPosition(it.value()[i].listener->position(), it.key(), i);
00316             }
00317         }
00318     }
00319 
00320     void PhyObjectsGroup::preUpdate()
00321     {
00322     }
00323 
00324     void PhyObjectsGroup::postUpdate()
00325     {
00326     }
00327 
00328     void PhyObjectsGroup::changedMatrix()
00329     {
00330         // First of all setting the transformation matrix for the head object to the
00331         // matrix for this object
00332         m_headObject->setMatrix(matrix());
00333 
00334         // Now setting transformation matrices for all other objects
00335         for (QMap<ChainIDType, QVector<ObjectAndMatrix> >::iterator it = m_objects.begin(); it != m_objects.end(); it++) {
00336             for (int i = 0; i < it.value().size(); i++) {
00337                 it.value()[i].object->setMatrix(it.value()[i].matrix * matrix());
00338             }
00339         }
00340 
00341         // Finally updating all joints
00342         for (QMap<ChainIDType, QVector<DOFAndListener> >::iterator it = m_joints.begin(); it != m_joints.end(); it++) {
00343             for (int i = 0; i < it.value().size(); i++) {
00344                 it.value()[i].joint->updateJointInfo();
00345             }
00346         }
00347     }
00348 
00349     KinematicLinkInfo::KinematicLinkInfo() :
00350         QObject(),
00351         m_buddies(),
00352         m_isMasterBuddy(true),
00353         m_chain(NULL),
00354         m_linkID(0),
00355         m_wObject(NULL),
00356         m_objectMatrix(wMatrix::identity()),
00357         m_axis(),
00358         m_bottom(),
00359         m_top(),
00360         m_height(0.0),
00361         m_worldTm(&s_identityMatrix),
00362         m_phyJoint(NULL),
00363         m_phyJointDOF(0),
00364         m_invertedJointAxis(true),
00365         m_nextAngle(0.0),
00366         m_velocity(0.0),
00367         m_motionMode(PhyDOF::off),
00368         m_linkAngleUpdated(true)
00369     {
00370     }
00371 
00372     KinematicLinkInfo::KinematicLinkInfo(iCub::iKin::iKinLimb* chain, unsigned int linkID) :
00373         QObject(),
00374         m_buddies(),
00375         m_isMasterBuddy(true),
00376         m_chain(chain),
00377         m_linkID(linkID),
00378         m_wObject(NULL),
00379         m_objectMatrix(wMatrix::identity()),
00380         m_axis(),
00381         m_bottom(),
00382         m_top(),
00383         m_height(0.0),
00384         m_worldTm(&s_identityMatrix),
00385         m_phyJoint(NULL),
00386         m_phyJointDOF(0),
00387         m_invertedJointAxis(true),
00388         m_nextAngle(0.0),
00389         m_velocity(0.0),
00390         m_motionMode(PhyDOF::off),
00391         m_linkAngleUpdated(true)
00392     {
00393         updateInformationFromiKin();
00394     }
00395 
00396     KinematicLinkInfo::KinematicLinkInfo(const KinematicLinkInfo& other) :
00397         QObject(),
00398         m_buddies(other.m_buddies),
00399         m_isMasterBuddy(other.m_isMasterBuddy),
00400         m_chain(other.m_chain),
00401         m_linkID(other.m_linkID),
00402         m_wObject(other.m_wObject),
00403         m_objectMatrix(other.m_objectMatrix),
00404         m_axis(other.m_axis),
00405         m_bottom(other.m_bottom),
00406         m_top(other.m_top),
00407         m_height(other.m_height),
00408         m_worldTm(other.m_worldTm),
00409         m_phyJoint(other.m_phyJoint),
00410         m_phyJointDOF(other.m_phyJointDOF),
00411         m_invertedJointAxis(other.m_invertedJointAxis),
00412         m_nextAngle(other.m_nextAngle),
00413         m_velocity(other.m_velocity),
00414         m_motionMode(other.m_motionMode),
00415         m_linkAngleUpdated(other.m_linkAngleUpdated)
00416     {
00417         // Adding the object we are copying in the list of our buddies and removing ourself
00418         m_buddies.insert(const_cast<KinematicLinkInfo*>(&other));
00419         m_buddies.remove(this);
00420 
00421         // Now adding ourself to our buddies' buddies
00422         foreach (KinematicLinkInfo* buddy, m_buddies) {
00423             buddy->m_buddies.insert(this);
00424         }
00425     }
00426 
00427     KinematicLinkInfo& KinematicLinkInfo::operator=(const KinematicLinkInfo& other)
00428     {
00429         if (&other == this) {
00430             return *this;
00431         }
00432 
00433         m_chain = other.m_chain;
00434         m_isMasterBuddy = other.m_isMasterBuddy;
00435         m_linkID = other.m_linkID;
00436         m_wObject = other.m_wObject;
00437         m_objectMatrix = other.m_objectMatrix;
00438         m_axis = other.m_axis;
00439         m_bottom = other.m_bottom;
00440         m_top = other.m_top;
00441         m_height = other.m_height;
00442         m_worldTm = other.m_worldTm;
00443         m_phyJoint = other.m_phyJoint;
00444         m_phyJointDOF = other.m_phyJointDOF;
00445         m_invertedJointAxis = other.m_invertedJointAxis;
00446         m_nextAngle = other.m_nextAngle;
00447         m_velocity = other.m_velocity;
00448         m_motionMode = other.m_motionMode;
00449         m_linkAngleUpdated = other.m_linkAngleUpdated;
00450 
00451         // Copying and updating the list of buddies
00452         m_buddies = other.m_buddies;
00453 
00454         // Adding the object we are copying in the list of our buddies and removing ourself
00455         m_buddies.insert(const_cast<KinematicLinkInfo*>(&other));
00456         m_buddies.remove(this);
00457 
00458         // Now adding ourself to our buddies' buddies
00459         foreach (KinematicLinkInfo* buddy, m_buddies) {
00460             buddy->m_buddies.insert(this);
00461         }
00462 
00463         return *this;
00464     }
00465 
00466     KinematicLinkInfo::~KinematicLinkInfo()
00467     {
00468         // Removing ourself from all buddies
00469         foreach (KinematicLinkInfo* buddy, m_buddies) {
00470             buddy->m_buddies.remove(this);
00471         }
00472     }
00473 
00474     void KinematicLinkInfo::setBuddies(QSet<KinematicLinkInfo*> buddies)
00475     {
00476         m_buddies = buddies;
00477         m_isMasterBuddy = true;
00478 
00479         // Making sure we are not in the list of our buddies (to avoid
00480         // infinite recursion)
00481         m_buddies.remove(this);
00482 
00483         // Setting the buddy list to all buddies
00484         foreach (KinematicLinkInfo *buddy, m_buddies) {
00485             buddy->m_buddies = m_buddies;
00486             buddy->m_isMasterBuddy = false;
00487 
00488             // Removing buddy from its list and adding ourself
00489             buddy->m_buddies.remove(buddy);
00490             buddy->m_buddies.insert(this);
00491 
00492             // Now syncing buddy to my values
00493             buddy->m_wObject = m_wObject;
00494             buddy->m_objectMatrix = m_objectMatrix;
00495             buddy->m_axis = m_axis;
00496             buddy->m_bottom = m_bottom;
00497             buddy->m_top = m_top;
00498             buddy->m_height = m_height;
00499             buddy->m_worldTm = m_worldTm;
00500             buddy->m_phyJoint = m_phyJoint;
00501             buddy->m_phyJointDOF = m_phyJointDOF;
00502             buddy->m_invertedJointAxis = m_invertedJointAxis;
00503             buddy->m_nextAngle = m_nextAngle;
00504             buddy->m_velocity = m_velocity;
00505             buddy->m_motionMode = m_motionMode;
00506             buddy->m_linkAngleUpdated = m_linkAngleUpdated;
00507         }
00508     }
00509 
00510     void KinematicLinkInfo::setWObject(WObject* wObject, const wMatrix &m)
00511     {
00512         // Calling the "NoBuddies" version for me and all buddies
00513         setWObject_NB(wObject, m);
00514         foreach (KinematicLinkInfo *buddy, m_buddies) {
00515             buddy->setWObject_NB(wObject, m);
00516         }
00517 
00518         // Now also updating wObject matrix
00519         updateMatrixFromiKin();
00520     }
00521 
00522     void KinematicLinkInfo::setWorldMatrix(const wMatrix *mtr)
00523     {
00524         // Calling the "NoBuddies" version for me and all buddies
00525         setWorldMatrix_NB(mtr);
00526         foreach (KinematicLinkInfo *buddy, m_buddies) {
00527             buddy->setWorldMatrix_NB(mtr);
00528         }
00529 
00530         // Now also updating wObject matrix
00531         updateMatrixFromiKin();
00532     }
00533 
00534     void KinematicLinkInfo::updateInformationFromiKin()
00535     {
00536         // Calling the "NoBuddies" version for me and all buddies
00537         updateInformationFromiKin_NB();
00538         foreach (KinematicLinkInfo *buddy, m_buddies) {
00539             buddy->updateInformationFromiKin_NB();
00540         }
00541     }
00542 
00543     void KinematicLinkInfo::updateMatrixFromiKin()
00544     {
00545         // Calling the "NoBuddies" version for me and all buddies
00546         updateMatrixFromiKin_NB();
00547         foreach (KinematicLinkInfo *buddy, m_buddies) {
00548             buddy->updateMatrixFromiKin_NB();
00549         }
00550     }
00551 
00552     void KinematicLinkInfo::setJoint(PhyJoint *joint, bool invertedJointAxis, unsigned int dof, bool doConnection, Qt::ConnectionType connType)
00553     {
00554         // Calling the "NoBuddies" version for me and all buddies
00555         setJoint_NB(joint, invertedJointAxis, dof, doConnection, connType);
00556         foreach (KinematicLinkInfo *buddy, m_buddies) {
00557             // Here we don't connect the signal, as when my setLinkAngle is
00558             // called, I take care of updating all buddies
00559             buddy->setJoint_NB(joint, invertedJointAxis, dof, false);
00560         }
00561     }
00562 
00563     void KinematicLinkInfo::setLinkAngle(real newAngle)
00564     {
00565         // Calling the "NoBuddies" version for me and all buddies.
00566         setLinkAngle_NB(newAngle);
00567         foreach (KinematicLinkInfo *buddy, m_buddies) {
00568             buddy->setLinkAngle_NB(newAngle);
00569         }
00570     }
00571 
00572     void KinematicLinkInfo::setDesideredPosition(real desideredAngle)
00573     {
00574         // Calling the "NoBuddies" version for me and all buddies
00575         setDesideredPosition_NB(desideredAngle);
00576         foreach (KinematicLinkInfo *buddy, m_buddies) {
00577             buddy->setDesideredPosition_NB(desideredAngle);
00578         }
00579     }
00580 
00581     void KinematicLinkInfo::setDesideredVelocity(real velocity)
00582     {
00583         // Calling the "NoBuddies" version for me and all buddies
00584         setDesideredVelocity_NB(velocity);
00585         foreach (KinematicLinkInfo *buddy, m_buddies) {
00586             buddy->setDesideredVelocity_NB(velocity);
00587         }
00588     }
00589 
00590     void KinematicLinkInfo::setiKinLinkLimits(real min, real max)
00591     {
00592         // Calling the "NoBuddies" version for me and all buddies
00593         setiKinLinkLimits_NB(min, max);
00594         foreach (KinematicLinkInfo *buddy, m_buddies) {
00595             buddy->setiKinLinkLimits_NB(min, max);
00596         }
00597     }
00598 
00599     void KinematicLinkInfo::updateLink()
00600     {
00601         // Calling the "NoBuddies" version for me and all buddies.
00602         updateLink_NB();
00603         foreach (KinematicLinkInfo *buddy, m_buddies) {
00604             buddy->updateLink_NB();
00605         }
00606     }
00607 
00608     void KinematicLinkInfo::setWObject_NB(WObject* wObject, const wMatrix &m)
00609     {
00610         m_wObject = wObject;
00611         m_objectMatrix = m;
00612     }
00613 
00614     void KinematicLinkInfo::setWorldMatrix_NB(const wMatrix *mtr)
00615     {
00616         if (mtr == NULL) {
00617             m_worldTm = &s_identityMatrix;
00618         } else {
00619             m_worldTm = mtr;
00620         }
00621     }
00622 
00623     void KinematicLinkInfo::updateInformationFromiKin_NB()
00624     {
00625         // Updating world matrix and other structures
00626 
00627         // Getting our frame of reference
00628         wMatrix thisMatrix;
00629         convertYarpMatrixToWorldMatrix(m_chain->getH(m_linkID, true), thisMatrix);
00630 
00631         // Getting the frame of reference for the previous link (we need it to
00632         // compute other stuffs)
00633         wMatrix prevLinkMatrix;
00634         if (m_linkID == 0) {
00635             convertYarpMatrixToWorldMatrix(m_chain->getH0(), prevLinkMatrix);
00636         } else {
00637             convertYarpMatrixToWorldMatrix(m_chain->getH(m_linkID - 1, true), prevLinkMatrix);
00638         }
00639 
00640         // Computing link information
00641         m_bottom = prevLinkMatrix.w_pos;
00642         m_top = thisMatrix.w_pos;
00643         m_axis = m_top - m_bottom;
00644         m_height = m_axis.norm();
00645         m_rotAxis = thisMatrix.unrotateVector(prevLinkMatrix.z_ax);
00646         m_rotCenter = thisMatrix.untransformVector(prevLinkMatrix.w_pos);
00647     }
00648 
00649     void KinematicLinkInfo::updateMatrixFromiKin_NB()
00650     {
00651         if ((m_isMasterBuddy) && (m_wObject != NULL)) {
00652             // Updating our frame of reference
00653             wMatrix thisMatrix;
00654             convertYarpMatrixToWorldMatrix(m_chain->getH(m_linkID, true), thisMatrix);
00655             thisMatrix = m_objectMatrix * thisMatrix * (*m_worldTm);
00656             m_wObject->setMatrix(thisMatrix);
00657         }
00658     }
00659 
00660     void KinematicLinkInfo::setJoint_NB(PhyJoint *joint, bool invertedJointAxis, unsigned int dof, bool doConnection, Qt::ConnectionType connType)
00661     {
00662         // First disconnecting signal from the previous joint dof (if we were connected)
00663         if (m_phyJoint != NULL) {
00664             disconnect(m_phyJoint->dofs()[m_phyJointDOF], SIGNAL(changedPosition(real)), this, SLOT(setLinkAngle(real)));
00665             disconnect(m_phyJoint->dofs()[m_phyJointDOF], SIGNAL(changedDesiredPosition(real)), this, SLOT(setDesideredPosition(real)));
00666             disconnect(m_phyJoint->dofs()[m_phyJointDOF], SIGNAL(changedDesiredVelocity(real)), this, SLOT(setDesideredVelocity(real)));
00667             disconnect(m_phyJoint->dofs()[m_phyJointDOF], SIGNAL(changedLimits(real, real)), this, SLOT(setiKinLinkLimits(real, real)));
00668         }
00669 
00670         m_phyJoint = joint;
00671         m_phyJointDOF = dof;
00672         m_invertedJointAxis = invertedJointAxis;
00673 
00674         if (doConnection) {
00675             connect(m_phyJoint->dofs()[m_phyJointDOF], SIGNAL(changedPosition(real)), this, SLOT(setLinkAngle(real)), connType);
00676             connect(m_phyJoint->dofs()[m_phyJointDOF], SIGNAL(changedDesiredPosition(real)), this, SLOT(setDesideredPosition(real)), connType);
00677             connect(m_phyJoint->dofs()[m_phyJointDOF], SIGNAL(changedDesiredVelocity(real)), this, SLOT(setDesideredVelocity(real)), connType);
00678             connect(m_phyJoint->dofs()[m_phyJointDOF], SIGNAL(changedLimits(real, real)), this, SLOT(setiKinLinkLimits(real, real)), connType);
00679         }
00680     }
00681 
00682     void KinematicLinkInfo::setLinkAngle_NB(real newAngle)
00683     {
00684         if (!m_invertedJointAxis) {
00685             newAngle = -newAngle;
00686         }
00687         (*(m_chain->asChain()))[m_linkID].setAng(newAngle);
00688         // Resetting m_nextAngle
00689         m_nextAngle = newAngle;
00690     }
00691 
00692     void KinematicLinkInfo::setDesideredPosition_NB(real desideredAngle)
00693     {
00694         // Saving the desidered angle and setting the motion mode
00695         if (m_invertedJointAxis) {
00696             m_nextAngle = desideredAngle;
00697         } else {
00698             m_nextAngle = -desideredAngle;
00699         }
00700         m_motionMode = PhyDOF::pos;
00701         m_linkAngleUpdated = false;
00702     }
00703 
00704     void KinematicLinkInfo::setDesideredVelocity_NB(real velocity)
00705     {
00706         // Checking the velocity is not grater than the highest possible velocity
00707         if (fabs(velocity) > fabs(m_phyJoint->dofs()[m_phyJointDOF]->maxVelocity())) {
00708             velocity = (velocity > 0) ? fabs(m_phyJoint->dofs()[m_phyJointDOF]->maxVelocity()) : -fabs(m_phyJoint->dofs()[m_phyJointDOF]->maxVelocity());
00709         }
00710         // Saving the desidered angle and setting the motion mode
00711         if (m_invertedJointAxis) {
00712             m_velocity = velocity;
00713         } else {
00714             m_velocity = -velocity;
00715         }
00716         m_motionMode = PhyDOF::vel;
00717         m_linkAngleUpdated = false;
00718     }
00719 
00720     void KinematicLinkInfo::setiKinLinkLimits_NB(real min, real max)
00721     {
00722         if (m_invertedJointAxis) {
00723             (*(m_chain->asChain()))[m_linkID].setMin(min);
00724             (*(m_chain->asChain()))[m_linkID].setMax(max);
00725         } else {
00726             (*(m_chain->asChain()))[m_linkID].setMin(-max);
00727             (*(m_chain->asChain()))[m_linkID].setMax(-min);
00728         }
00729     }
00730 
00731     void KinematicLinkInfo::updateLink_NB()
00732     {
00733         // It is ok to do this because the motor control calls setDesideredVelocity
00734         // at each time step (otherwise we would only do one step and then stop)
00735         if (m_linkAngleUpdated) {
00736             return;
00737         }
00738 
00739         // Here we also update the DOF velocity and position
00740         real velocity = 0.0;
00741         real position = (*(m_chain->asChain()))[m_linkID].getAng();
00742         switch (m_motionMode) {
00743             case PhyDOF::force:
00744                 {
00745                     // Not supported (never will)
00746                 }
00747                 break;
00748             case PhyDOF::vel:
00749                 {
00750                     // Here we have to invert the angle if the axis is not inverted to balance the
00751                     // inversion done in the setLinkAngle function (this is to avoid having two versions
00752                     // of setLinkAngle, one that inverts the angle if it has to, and another that
00753                     // never inverts angles). We also have to multiply velocity by the timestep to have the
00754                     // actual delta angle
00755                     const real deltaAngle = m_velocity * m_phyJoint->world()->timeStep();
00756                     velocity = m_velocity;
00757                     position = (*(m_chain->asChain()))[m_linkID].getAng() + deltaAngle;
00758                     if (m_invertedJointAxis) {
00759                         setLinkAngle_NB(position);
00760                     } else {
00761                         setLinkAngle_NB(-position);
00762                     }
00763                 }
00764                 break;
00765             case PhyDOF::pos:
00766                 {
00767                     // Here we have to invert the angle if the axis is not inverted to balance the
00768                     // inversion done in the setLinkAngle function (this is to avoid having two versions
00769                     // of setLinkAngle, one that inverts the angle if it has to, and another that
00770                     // never inverts angles)
00771                     velocity = (m_nextAngle - (*(m_chain->asChain()))[m_linkID].getAng()) / m_phyJoint->world()->timeStep();
00772                     position = m_nextAngle;
00773                     if (m_invertedJointAxis) {
00774                         setLinkAngle_NB(position);
00775                     } else {
00776                         setLinkAngle_NB(-position);
00777                     }
00778                 }
00779                 break;
00780             case PhyDOF::off:
00781                 {
00782                     // Nothing to do, here
00783                 }
00784                 break;
00785         }
00786 
00787         // Updating velocity and position
00788         m_phyJoint->dofs()[m_phyJointDOF]->setPosition(position);
00789         m_phyJoint->dofs()[m_phyJointDOF]->setVelocity(velocity);
00790         m_linkAngleUpdated = true;
00791     }
00792 
00793     const wMatrix KinematicLinkInfo::s_identityMatrix(wMatrix::identity());
00794 } // end namespace farsa
00795 
00796 #endif // FARSA_USE_YARP_AND_ICUB