basic/kinematics/Jacobian.cpp

Go to the documentation of this file.
00001 
00002 //
00003 //Contents: Class CJacobian.
00004 // 
00005 //Revision History:
00006 //       Date     Author    Description
00007 //      ---------------------------------------------------------
00008 //     Feb-2004:  G.Sheung  First version implemented
00009 //     Jun-2004:  Z.Yao     Adapted, associate with a robot
00010 //     Oct-2004:  Z.Yao     Adapted, for SSRMS/SPDM, where a part of robot need to do 
00011 //                          the planning independently.
00012 //     Nov-2004:  Z.Yao     Comments added
00013 //  
00014 //Notes:
00015 //   1. The typical procedure to call CJacobian is as follows
00016 //      a. Create a entity of class CJacobian, say $jacobian$, by associating it with a robot;
00017 //      b. jacobian.SetConfiguration($conf$); 
00018 //         After this point you can jacobian.GetJointFrame(...) or jacobian.GetJointWorldFrame(...)
00019 //         to get the frame of each joint;
00020 //      c. jacobian.SetInterestPoint(...).
00021 //         After this point you can get the jacobian matrix, since it has been computed inside.
00022 //      d. jacobian.GetJointVelocity(...), or jacobian.GetPhyVelocity(...)
00023 //         Get joint-space velocity or physical-space velocity by the other velocity.
00024 //
00026 #include <malloc.h>
00027 #include <assert.h>
00028 #include <math.h>
00029 #include "Jacobian.h"
00030 #include "DH_Link.h"
00031 #include "math\Matrixmxn.h"
00032 #include "math\VectorN.h"
00033 #include "math\Vector4.h"
00034 
00035 #define PI 3.1415926535897932384
00036 #define END_EFF_DOF   2
00037 
00038 CJacobian::CJacobian(RobotBase& robot)
00039 {
00040     m_pRobot = &robot;
00041     m_nDof = robot.DOF();
00042     m_configCurrent.SetNumDOF(m_nDof);
00043     m_bOrientation = false;
00044     m_bPosition = true;
00045     m_nJoint = m_nDof;
00046     m_pMatrix = new Matrixmxn(3, m_nDof);
00047     m_pJointMatrix = new Matrix4x4[m_nDof];
00048     m_pJointOrig = new Vector4[m_nDof];
00049     m_pJointZ = new Vector4[m_nDof];
00050 }
00051 
00052 CJacobian::~CJacobian()
00053 {
00054     delete (m_pMatrix);
00055     delete [] m_pJointMatrix;
00056     delete [] m_pJointOrig;
00057     delete [] m_pJointZ;
00058 }
00059 
00060 //------------------------------------------------------------------
00061 //SetInterestPoint
00062 //
00063 //This function is used to compute the Jacobian matrix.
00064 //
00065 //Input Parameter:
00066 //      joint    : Target joint, for example, the joint to which the end-effect attach 
00067 //      endFrame : (config., pose) of the direction
00068 //      position : To consider position or not.
00069 //      orient   : To consider orientation or not.
00070 //      baseJoint: First joint of the planning part;
00071 //
00072 //Ouput Parameter:
00073 //      N.A
00074 //
00075 //Return Value:
00076 //      true/false.
00077 //
00078 //Notes:
00079 //   1. At the end of this function call, m_pMatrix will be updated with the newly-computed jacobain matrix.
00080 //   2. Taking SSRMS/SPDM as an exmple, a robot with three arms, consiting of 29 joints, 
00081 //      in one of the tasks, it plans for one of the arms, 7-joint, joint 8-14,
00082 //      then this function will be called like: 
00083 //          SetInterestPoint(14, $endFrame$, true, true, 7);
00084 //      where $endFrame$ it the end-effector tool frame w.r.t joint-14.
00085 //      
00086 //------------------------------------------------------------------
00087 // Given a joint regarded as wrist, and relative position
00088 bool CJacobian::SetInterestPoint(int joint, Frame& endFrame, bool position, bool orient, int baseJoint)
00089 {
00090     int m_nDof = m_pRobot->DOF();
00091 //      if (baseJoint>joint)
00092 //      {
00093 //              assert(false);
00094 //              return false;
00095 //      }
00096 
00097     if ((m_bPosition != position)||(m_bOrientation != orient) || (m_nJoint != joint) || (m_nBaseJoint!= baseJoint) )
00098     {
00099         m_frObserve = endFrame;
00100         m_nJoint = joint;
00101         m_bPosition = position;
00102         m_bOrientation = orient;
00103         m_nBaseJoint = baseJoint;
00104         delete m_pMatrix;
00105         if (orient && position)
00106         {
00107             m_pMatrix = new Matrixmxn(6, m_nDof);
00108         }
00109         else if (orient || position)
00110         {
00111             m_pMatrix = new Matrixmxn(3, m_nDof);
00112         }
00113         else
00114         {
00115                 assert(false);
00116                 return false;
00117         }
00118     }
00119 
00120     if (!Calculate())
00121     {
00122         return false;
00123     }
00124 
00125     return true;
00126 }
00127 
00128 // Determine physical velocity by joint velocity
00129 bool CJacobian::GetPhyVelocity(VectorN& phyVel, VectorN& jointVel)
00130 {
00131     assert(m_pMatrix->GetRows() == phyVel.Length());
00132     phyVel = (*m_pMatrix) * jointVel;
00133     return true;        
00134 }
00135 
00136 // Determine joint velocity by physical velocity
00137 bool CJacobian::GetJointVelocity(VectorN& jointVel, VectorN& phyVel)
00138 {
00139     Matrixmxn inv;
00140     m_pMatrix->Inverse(inv);
00141     jointVel = inv*phyVel;
00142     return true;
00143 }
00144 
00145 bool CJacobian::SetConfiguration(Configuration& conf)
00146 {
00147     m_configCurrent = conf;
00148     if (UpdateJoints())
00149         return true;
00150     else
00151         return false;
00152 }
00153     
00154 Matrixmxn* CJacobian::GetMatrix()
00155 {
00156     return m_pMatrix;
00157 }
00158 
00159 bool CJacobian::UpdateJoints()
00160 {
00161     std::list< LinkBase*> robotLinks = m_pRobot->GetAllLinks();
00162     std::list< LinkBase* >::iterator link = robotLinks.begin();
00163 
00164     Frame frame;
00165     for (int i = 0; i < m_nDof; i++, link++)
00166     {
00167         ((DH_Link *)(*link))->SetJointVariable(m_configCurrent[i]);
00168         frame *= ((DH_Link *)(*link))->GetFrame();
00169         m_pJointMatrix[i] = frame;
00170 
00171         m_pJointOrig[i] = frame.GetTranslationVector();
00172         m_pJointZ[i][0] = frame(0, 2);
00173         m_pJointZ[i][1] = frame(1, 2);
00174         m_pJointZ[i][2] = frame(2, 2);
00175     }
00176     return true;
00177 }
00178 
00179 bool CJacobian::Calculate()
00180 {
00181     assert(m_nDof >= m_nJoint);
00182 
00183     Vector4 pEndZ;
00184     Vector4 pEndOrig;
00185 
00186     Frame frame = m_pJointMatrix[m_nJoint];
00187     frame *= m_frObserve;
00188 
00189     pEndOrig = frame.GetTranslationVector();
00190     pEndZ[0] = frame(0, 2);
00191     pEndZ[1] = frame(1, 2);
00192     pEndZ[2] = frame(2, 2);
00193  
00194         
00195     for (int i = 0; i < m_nBaseJoint; i++)
00196     {
00197         int nRow=3;
00198         if ((m_bOrientation) && (m_bPosition))
00199             nRow = 6;
00200         for (int j = 0; j< nRow; j++)
00201         {
00202             m_pMatrix->SetValues(j, i, (double)0);
00203         }                       
00204     }
00205 
00206     // calculate Jacobian
00207     std::list< LinkBase*> robotLinks = m_pRobot->GetAllLinks();
00208     std::list< LinkBase* >::iterator link = robotLinks.begin();
00209     for (i = m_nBaseJoint; i <= m_nJoint; i++)
00210     {
00211         int jointType = ((DH_Link*)(*link))->GetJointType();
00212         assert((jointType == DH_THETA) || (jointType == DH_D));
00213 
00214         Vector4 pIPTool; // (p-p[i-1])
00215         Vector4 linearColumn;
00216         Vector4 angularColumn;
00217 
00218         //Compute jacobian column for linear velocity
00219         if (m_bPosition)
00220         {
00221             linearColumn = m_pJointZ[i]; //Prismatic joint, by default
00222             if (jointType == DH_THETA) //Revolute joint
00223             {
00224                 pIPTool = pEndOrig - m_pJointOrig[i];  // (Pobs - Piorg)
00225                 linearColumn = linearColumn.Cross(pIPTool);
00226             }
00227 
00228             for (int j = 0; j < 3; j++)
00229             {
00230                 m_pMatrix->SetValues(j, i, linearColumn[j]);
00231             }
00232         }
00233 
00234         //Compute jacobian column for angular velocity
00235         if (m_bOrientation)
00236         {
00237             angularColumn *= 0; //clear variable, Prismatic joint, by default
00238             if (jointType == DH_THETA) //Revolute joint
00239             {
00240                 angularColumn = m_pJointZ[i];
00241             }
00242             int offset = (m_bPosition)?3:0;
00243             for (int j = 0 ; j < 3; j++)
00244             {
00245                 m_pMatrix->SetValues(offset+j, i, angularColumn[j]);
00246             }
00247         }
00248         link++;
00249     }   // Jacobian matrix calculated
00250 
00251     for (i = m_nJoint+1; i < m_nDof; i++)
00252     {
00253         int nRow=3;
00254         if ((m_bOrientation) && (m_bPosition))
00255             nRow = 6;
00256         for (int j = 0; j< nRow; j++)
00257         {
00258             m_pMatrix->SetValues(j, i, (double)0);
00259         }                       
00260     }
00261 
00262     return true;
00263 }
00264 
00265 Frame CJacobian::GetJointFrame(int nJoint) const
00266 {
00267     Frame lastJoint;
00268     if (nJoint > 0)
00269     {
00270         lastJoint = m_pJointMatrix[nJoint-1].Inverse();
00271     }
00272     lastJoint *= m_pJointMatrix[nJoint];
00273     return lastJoint;
00274 }
00275 
00276 Frame CJacobian::GetJointWorldFrame(int nJoint) const
00277 {
00278     return m_pJointMatrix[nJoint];
00279 }
00280 

Generated on Sat Apr 1 21:30:34 2006 for Motion Planning Kernel by  doxygen 1.4.6-NO