Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

robot/KinematicChain

Go to the documentation of this file.
00001 /* **-*-c++-*-**************************************************************
00002   Copyright (C)2003 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008         
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013         
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018   $Id: KinematicChain 1039 2004-02-11 20:50:52Z jungd $
00019   $Revision: 1.8 $
00020   $Date: 2004-02-11 15:50:52 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #ifndef _ROBOT_KINEMATICCHAIN_
00026 #define _ROBOT_KINEMATICCHAIN_
00027 
00028 #include <robot/robot>
00029 
00030 #include <base/array>
00031 #include <base/Vector>
00032 #include <base/Matrix>
00033 #include <base/Serializer>
00034 #include <base/Externalizable>
00035 #include <base/Hashable>
00036 #include <robot/ManipulatorJointTrajectory>
00037 #include <robot/KinematicEvaluator>
00038 
00039 
00040 
00041 namespace robot {
00042 
00043 
00044 
00045 
00046 /// Describes a kinematic chain of links, each possibly with a joint
00047 class KinematicChain : public base::Serializable, public base::Externalizable, public base::Hashable
00048 {
00049 public:
00050 
00051   /// unit type of parameters
00052   enum UnitType { Distance, Angle };
00053   
00054   // consts used to indicate that joints have no limits
00055   static const Real unboundedMinAngleLimit; // = -consts::Pi - consts::epsilon;
00056   static const Real unboundedMaxAngleLimit; // = +consts::Pi + consts::epsilon;
00057   static const Real unboundedMinDistLimit; //  = consts::maxReal;
00058   static const Real unboundedMaxDistLimit; //  = -consts::maxReal;
00059   
00060 
00061   /// Parameters for a single joint
00062   class Link : public base::Serializable, public base::Externalizable, public base::Hashable
00063   {
00064   public:
00065     /// FixedTransform - link described by a 4x4 matrix transform, no joint
00066     /// Prismatic - link with a 1-dof D-H type joint that transltes along the joint z-axis (varies the d parameter)
00067     /// Revolute  - link with a 1-dof D-H type joint that rotates about the joint z-axis (varies the theta parameter)
00068     /// Translating - link with a 1-dof joint that translates along the specified direction vector
00069     enum LinkType {
00070       FixedTransform,
00071       Prismatic,      
00072       Revolute,
00073       Translating
00074     };
00075 
00076     Link() 
00077       :  alpha(0), a(1), d(0), theta(0), 
00078          jminLimit(0), jmaxLimit(0), jminAccel(0), jmaxAccel(0), 
00079          linkType(Revolute), active(true), hashDirty(true)
00080       {}
00081     Link(const Link& j)
00082       : alpha(j.alpha), a(j.a), d(j.d), theta(j.theta), direction(j.direction), t(j.t), transform(j.transform),
00083         jminLimit(j.jminLimit), jmaxLimit(j.jmaxLimit), jminAccel(j.jminAccel), jmaxAccel(j.jmaxAccel),
00084         linkType(j.linkType), active(j.active), hashDirty(true)
00085       {}
00086     Link(LinkType type, Real alpha, Real a, Real d, Real theta,
00087          Real minLimit=KinematicChain::unboundedMinAngleLimit, Real maxLimit=KinematicChain::unboundedMaxAngleLimit,
00088          Real minAccel=0, Real maxAccel=0,
00089          bool active=true)
00090       : alpha(alpha), a(a), d(d), theta(theta),
00091         jminLimit(minLimit), jmaxLimit(maxLimit), jminAccel(minAccel), jmaxAccel(maxAccel),
00092         linkType(type), active(active), hashDirty(true)
00093       {
00094         if (dofUnitType(0) == Distance) {
00095           if (Math::equals(minLimit, KinematicChain::unboundedMinAngleLimit))
00096             minLimit = KinematicChain::unboundedMinDistLimit;
00097           if (Math::equals(maxLimit, KinematicChain::unboundedMaxAngleLimit))
00098             maxLimit = KinematicChain::unboundedMaxDistLimit;
00099         }
00100       }
00101       
00102     Link(const Vector3& direction, Real t,
00103          Real minLimit=KinematicChain::unboundedMinDistLimit, Real maxLimit=KinematicChain::unboundedMaxDistLimit,
00104          Real minAccel=0, Real maxAccel=0,
00105          bool active=true)
00106       : direction(direction), t(t),
00107         jminLimit(minLimit), jmaxLimit(maxLimit), jminAccel(minAccel), jmaxAccel(maxAccel),
00108         linkType(Translating), active(active), hashDirty(true)
00109       {}
00110       
00111     Link(const Matrix4& fixedTransform)
00112       : transform(fixedTransform), linkType(FixedTransform), active(false), hashDirty(true)
00113       {}
00114 
00115     ~Link() {}
00116 
00117     virtual String className() const { return String("Link"); }
00118 
00119     Link& operator=(const Link& l);
00120 
00121     LinkType type() const { return linkType; }
00122     bool isActive() const { return active; }
00123     bool isDHType() const { return (linkType==Prismatic)||(linkType==Revolute); }
00124 
00125     /// the number of degrees-of-freedom present in this link's joint (0 if no joint)
00126     Int dof() const { return active?(isDHType()?1:(linkType==Translating?1:0)):0; } 
00127 
00128     UnitType dofUnitType(Int dof=0) const { return (isDHType() && (linkType==Revolute))?Angle:Distance; }
00129 
00130     /// the forward kinematic transform for this link, with variable parameter values q (dim q must be link.dof())
00131     Matrix kinematicTransform(const base::Vector& q) const;
00132     
00133     
00134     // applicable to Denavit-Hartenberg type links only (Revolute, Prismatic)
00135     Real getAlpha() const { return alpha; }  ///< get twist angle (const) (radians)
00136     Real getA() const { return a; }          ///< get link length (const)
00137     Real getD() const { return d; }          ///< get distance between links (home pos)
00138     Real getTheta() const { return theta; }  ///< get angle between links (home pos) (radians)
00139     
00140     void setAlpha(Real alpha) { this->alpha=alpha; dirtyHash(); }
00141     void setA(Real a) { this->a = a; dirtyHash(); }
00142     void setD(Real d) { this->d = d; dirtyHash(); }
00143     void setTheta(Real theta) { this->theta = theta; dirtyHash(); }
00144     
00145     // Translating links
00146     Vector3 getDirection() const { return direction; }  ///< get direction along which the joint translates by the variable distance
00147     Real getT() const { return t; }          ///< get distance to translate along direction (home pos)
00148 
00149     void setDirection(const Vector3& dir) { direction = dir; dirtyHash(); }
00150     void setT(Real t) { this->t = t; dirtyHash(); }
00151     
00152     /// FixedTransform links
00153     Matrix4 getTransform() const { return transform; } 
00154     void setTransform(const Matrix4& transform) { this->transform = transform; dirtyHash(); }
00155     
00156      
00157     Real variable(Int dof=0) const {
00158       Assert(dof < this->dof());
00159       if (isDHType()) 
00160         return (linkType==Revolute)?theta:d;
00161       else if (linkType==Translating)
00162         return t;
00163       throw std::runtime_error(Exception("unhandled KinematicChain::Link type"));
00164     }
00165     
00166     Real minLimit(Int dof=0) const { return jminLimit; }
00167     Real maxLimit(Int dof=0) const { return jmaxLimit; }
00168     Real minAccel(Int dof=0) const { return jminAccel; }
00169     Real maxAccel(Int dof=0) const { return jmaxAccel; }
00170 
00171     bool operator==(const Link& l) const;
00172     bool operator!=(const Link& l) const { return !(*this == l); }
00173 
00174     virtual void serialize(base::Serializer& s)
00175       {
00176         s(linkType,"type");
00177         if (linkType==Translating)
00178           s(direction,"direction");
00179         else {
00180           s(alpha,"alpha")(a,"a")(d,"d")(theta,"theta");
00181         }
00182         s(jminLimit,"minLimit")(jmaxLimit,"maxLimit"); 
00183         s(jminAccel,"minAccel")(jmaxAccel,"maxAccel");
00184         s(active,"active");
00185         if (s.isInput()) dirtyHash(); 
00186       }
00187 
00188     // Externalizable
00189     virtual bool formatSupported(const String format, Real version = 1.0, ExternalizationType type = IO) const ///< query if specific format is supported (for input, output or both)
00190       { return ( (format=="xml") && (version==1.0) ); }
00191     virtual void externalize(base::Externalizer& e, String format = "", Real version = 1.0);
00192     virtual void externalize(base::Externalizer& e, String format = "", Real version = 1.0) const
00193       { Externalizable::externalize(e, format, version); }
00194 
00195     // Hashable
00196     virtual base::array<base::Byte> hashCode() const;
00197     
00198     
00199   protected:
00200     // Denavit-Hartenberg (Revolute, Prismatic)
00201     Real alpha;  ///< twist angle (const) (radians)
00202     Real a;      ///< link length (const)
00203     Real d;      ///< distance between links (home pos)
00204     Real theta;  ///< angle between links (home pos) (radians)
00205 
00206     // Translating
00207     Vector3 direction; ///< direction along which the joint translates by the variable distance
00208     Real t;            ///< distance to translate along direction (home pos)
00209     
00210     /// FixedTransform
00211     Matrix4 transform;
00212 
00213     Real jminLimit, jmaxLimit; ///< joint limits
00214     Real jminAccel, jmaxAccel; ///< joint acceleration limits
00215 
00216     LinkType linkType;
00217     bool active; ///< an inactive link's joints can't move
00218     
00219     String frameName; ///< reference frame name of this link, or "" if unknown/unnamed
00220 
00221     mutable bool hashDirty;
00222     mutable array<base::Byte> hash;
00223     void dirtyHash() const { hashDirty=true; }
00224     
00225     friend class KinematicChain;
00226   };
00227 
00228 
00229 
00230   KinematicChain() ///< empty chain (no links)
00231     : hashDirty(true) { initKinematicEvaluator(); }
00232   KinematicChain(const Link& l) ///< 'chain' comprising a single link
00233     : links(1), hashDirty(true) { initKinematicEvaluator(); links[0] = l; computeVariables(); }
00234 
00235   KinematicChain(const KinematicChain& kc) 
00236     : links(kc.links), variables(kc.variables), kinematicEvaluator(kc.kinematicEvaluator), hashDirty(true) {}
00237 
00238 
00239   virtual String className() const { return String("KinematicChain"); }
00240 
00241   KinematicChain& operator=(const KinematicChain& kc) 
00242     { links=kc.links; variables=kc.variables; dirtyHash(); return *this; }
00243 
00244 
00245 
00246   Int size() const { return links.size(); } ///< no. of links in the chain
00247   Int dof() const { return variables.size(); } ///< no. of degrees-of-freedom (sum of joint variables for each link)
00248 
00249   bool isDHType() const; ///< true if the chain is comprised only of links for which link.isDHType() is true
00250   
00251   const Link& operator[](Int i) const { return links[i]; }
00252   void setLink(Int i, const Link& link) { links[i] = link; dirtyHash(); }
00253 
00254   const Link& at(Int i) const { Assert(i < size()); return links[i]; }
00255   void setLinkAt(Int i, const Link& link) { Assert(i < size()); links[i] = link; dirtyHash(); }
00256 
00257   /// get link that described joint controlled by variable i (0 <= i < dof())
00258   const Link& linkOfVariable(Int i) const { Assert(i < dof()); return links[variables[i].first]; }
00259   //Link& linkOfVariable(Int i) { Assert(i < dof()); return links[variables[i].first]; }
00260 
00261   Int linkIndexOfVariable(Int i) const { Assert(i < dof()); return variables[i].first; }
00262 
00263   UnitType variableUnitType(Int i) const
00264     { Assert(i < dof()); return linkOfVariable(i).dofUnitType( variables[i].second ); }
00265 
00266   Real variableMinLimit(Int i) const { return linkOfVariable(i).minLimit(variables[i].second); }
00267   Real variableMaxLimit(Int i) const { return linkOfVariable(i).maxLimit(variables[i].second); }
00268   Real variableMinAccel(Int i) const { return linkOfVariable(i).minAccel(variables[i].second); }
00269   Real variableMaxAccel(Int i) const { return linkOfVariable(i).maxAccel(variables[i].second); }
00270 
00271 
00272   void activateLink(Int i, bool active=true)
00273     { Assert(i < size()); links[i].active=active; computeVariables(); dirtyHash(); }
00274   bool linkIsActive(Int i) const { Assert(i < size()); return links[i].isActive(); }
00275 
00276 
00277   Link front() const { Assert(size()>0); return links[0]; }
00278   Link back() const  { Assert(size()>0); return links[size()-1]; }
00279 
00280   void push_back(const Link& l)
00281     { links.at(size())=l; computeVariables(); dirtyHash(); }
00282 
00283   void pop_back() 
00284     { links.resize( size()-1 ); computeVariables(); dirtyHash(); }
00285   
00286   void resize(Int newsize)
00287     { links.resize(newsize); computeVariables(); dirtyHash(); }
00288 
00289   
00290   KinematicChain subChain(Int first, Int count) const;
00291 
00292   bool operator==(const KinematicChain& kc) const { return links==kc.links; }
00293   bool operator!=(const KinematicChain& kc) const { return links!=kc.links; }
00294 
00295   KinematicChain& operator+=(const KinematicChain& kc);
00296   
00297   KinematicChain& insert(Int pos, const KinematicChain& kc);
00298   KinematicChain& insert(Int pos, const Link& l);
00299   KinematicChain& erase(Int pos);
00300   KinematicChain& erase(Int first, Int last);
00301 
00302 
00303   // coordinate transform support
00304   void setInitialFrame(const String& name) { initialFrame = name; dirtyHash(); }
00305   const String& getInitialFrame() const { return initialFrame; }
00306   
00307   void setLinkFrame(Int i, const String& name) { Assert(i < size()); links[i].frameName = name; dirtyHash(); }
00308   const String& getLinkFrame(Int i) const { Assert(i < size()); return links[i].frameName; }
00309   
00310   /// transform point v from the reference frame of link i to the frame of link j, when chain is in configuration q
00311   Vector transform(Int fromLink, Int toLink, const Vector& v, const Vector& q) const;
00312 
00313   /// transform point v from reference frame 'fromFrame' to 'toFrame' when chain is in cofiguration q
00314   ///  e.g. if from=='ee' and to=='world', passing v=0 will give the ee coords. in the world frame
00315   ///    (if 'ee' and 'world' are appropriately defined frame names)
00316   ///  throws invalid_argument exception if either link frame names are unknown
00317   Vector transform(const String& fromFrame, const String& toFrame, const Vector& v, const Vector& q) const;
00318   
00319   
00320   /// get the forward kinematics transform for joint parameters q
00321   Matrix getForwardKinematics(const Vector& q) const;
00322   
00323   /// get the Jacobian matrix for joint parameters q
00324   Matrix getJacobian(const Vector& q, bool includeOrientation = true) const;
00325 
00326   /// get an array of the joint origin locations for parameters q
00327   array<Vector> getJointOrigins(const Vector& q) const;
00328 
00329     /// get an array of the link origin locations for parameters q
00330   array<Vector> getLinkOrigins(const Vector& q) const;
00331 
00332 
00333   void setKinematicEvaluator(ref<KinematicEvaluator> evaluator)
00334     { kinematicEvaluator = evaluator; }
00335   
00336 
00337   /// convert the components of the joint vectors in jointTrajectory corresponding to Revolute joints of the chain to
00338   ///  the specified units
00339   void convertJointTrajectory(ManipulatorJointTrajectory& jointTrajectory, 
00340                               ManipulatorJointTrajectory::AngularUnits units = ManipulatorJointTrajectory::Radians) const
00341   {
00342     array<Int> components;
00343     for(Int v=0; v<dof(); v++)
00344       if (variableUnitType(v) == Angle)
00345         components.push_back(v);
00346     jointTrajectory.convertComponentUnits(components, units);
00347   }
00348 
00349 
00350   virtual void serialize(base::Serializer& s)
00351     { s(links,"links"); computeVariables(); if (s.isInput()) dirtyHash(); }
00352 
00353   // Externalizable
00354   virtual bool formatSupported(const String format, Real version = 1.0, ExternalizationType type = IO) const ///< query if specific format is supported (for input, output or both)
00355     { return ( (format=="xml") && (version==1.0) ); }
00356   virtual void externalize(base::Externalizer& e, String format = "", Real version = 1.0); ///< read or write object state to Externalizer
00357   virtual void externalize(base::Externalizer& e, String format = "", Real version = 1.0) const
00358     { Externalizable::externalize(e, format, version); }
00359 
00360   // Hashable
00361   virtual base::array<base::Byte> hashCode() const;
00362   
00363 protected:
00364   typedef base::array<Link> LinkArray;
00365 
00366   /// index is the variable no. for this chain, elements are a pair of Ints (link index, dof-index), where
00367   ///  link index is link correpsonding to this joint variable (index into LinkArray), and dof-index is the degree of freedom
00368   ///  for the link (for links representing joints with multiple dofs)
00369   typedef base::array<std::pair<Int,Int> > VariableIndexArray;
00370 
00371   KinematicChain(const LinkArray& la)
00372     : links(la), hashDirty(true) { computeVariables(); }
00373 
00374   void computeVariables(); ///< updates variables based on link joint dofs
00375 
00376   LinkArray links;
00377   VariableIndexArray variables;
00378 
00379   // class wide default evaluator
00380   static bool KinematicEvaluatorInitialized;
00381   static ref<KinematicEvaluator> defaultKinematicEvaluator;
00382 
00383   ref<KinematicEvaluator> kinematicEvaluator; ///< KinematicEvaluator instance to use for this chain
00384   
00385   String initialFrame;
00386   
00387   mutable bool hashDirty;
00388   mutable array<base::Byte> hash;
00389   void dirtyHash() const { hashDirty=true; }
00390   
00391   void initKinematicEvaluator(); 
00392 
00393 };
00394 
00395 
00396 
00397 std::ostream& operator<<(std::ostream& out, const robot::KinematicChain::Link& l); // Output
00398 
00399 inline std::ostream& operator<<(std::ostream& out, const robot::KinematicChain& c) // Output
00400 {
00401   out << "KinematicChain link parameters: ({} marks variable) - " << c.dof() << "-dof" << std::endl;
00402   for(Int i=0; i<c.size(); i++) 
00403     out << i << " - " << c[i];
00404   return out;
00405 }
00406 
00407 
00408 
00409 
00410 } // robot
00411 
00412 #endif

Generated on Thu Jul 29 15:56:36 2004 for OpenSim by doxygen 1.3.6