Blender V2.61 - r43446

MovingFrame.cpp

Go to the documentation of this file.
00001 
00004 /*
00005  * MovingFrame.cpp
00006  *
00007  *  Created on: Feb 10, 2009
00008  *      Author: benoitbolsee
00009  */
00010 
00011 #include "MovingFrame.hpp"
00012 #include <string.h>
00013 namespace iTaSC{
00014 
00015 static const unsigned int frameCacheSize = (sizeof(((Frame*)0)->p.data)+sizeof(((Frame*)0)->M.data))/sizeof(double);
00016 
00017 MovingFrame::MovingFrame(const Frame& frame):UncontrolledObject(),
00018     m_function(NULL), m_param(NULL), m_velocity(), m_poseCCh(-1), m_poseCTs(0)
00019 {
00020     m_internalPose = m_nextPose = frame;
00021     initialize(6, 1);
00022     e_matrix& Ju = m_JuArray[0];
00023     Ju = e_identity_matrix(6,6);
00024 }
00025 
00026 MovingFrame::~MovingFrame()
00027 {
00028 }
00029 
00030 void MovingFrame::finalize()
00031 {
00032     updateJacobian();
00033 }
00034 
00035 void MovingFrame::initCache(Cache *_cache)
00036 {
00037     m_cache = _cache;
00038     m_poseCCh = -1;
00039     if (m_cache) {
00040         m_poseCCh = m_cache->addChannel(this,"pose",frameCacheSize*sizeof(double));
00041         // don't store the initial pose, it's causing unnecessary large velocity on the first step
00042         //pushInternalFrame(0);
00043     }
00044 }
00045 
00046 void MovingFrame::pushInternalFrame(CacheTS timestamp)
00047 {
00048     if (m_poseCCh >= 0) {
00049         double buf[frameCacheSize];
00050         memcpy(buf, m_internalPose.p.data, sizeof(m_internalPose.p.data));
00051         memcpy(&buf[sizeof(m_internalPose.p.data)/sizeof(double)], m_internalPose.M.data, sizeof(m_internalPose.M.data));
00052 
00053         m_cache->addCacheVectorIfDifferent(this, m_poseCCh, timestamp, buf, frameCacheSize, KDL::epsilon);
00054         m_poseCTs = timestamp;
00055     }
00056 }
00057 
00058 // load pose just preceding timestamp
00059 // return false if no cache position was found
00060 bool MovingFrame::popInternalFrame(CacheTS timestamp)
00061 {
00062     if (m_poseCCh >= 0) {
00063         char *item;
00064         item = (char *)m_cache->getPreviousCacheItem(this, m_poseCCh, &timestamp);
00065         if (item && m_poseCTs != timestamp) {
00066             memcpy(m_internalPose.p.data, item, sizeof(m_internalPose.p.data));
00067             item += sizeof(m_internalPose.p.data);
00068             memcpy(m_internalPose.M.data, item, sizeof(m_internalPose.M.data));
00069             m_poseCTs = timestamp;
00070             // changing the starting pose, recompute the jacobian
00071             updateJacobian();
00072         }
00073         return (item) ? true : false;
00074     }
00075     // in case of no cache, there is always a previous position
00076     return true;
00077 }
00078 
00079 bool MovingFrame::setFrame(const Frame& frame)
00080 {
00081     m_internalPose = m_nextPose = frame;
00082     return true;
00083 }
00084 
00085 bool MovingFrame::setCallback(MovingFrameCallback _function, void* _param)
00086 {
00087     m_function = _function;
00088     m_param = _param;
00089     return true;
00090 }
00091 
00092 void MovingFrame::updateCoordinates(const Timestamp& timestamp)
00093 {
00094     // don't compute the velocity during substepping, it is assumed constant.
00095     if (!timestamp.substep) {
00096         bool cacheAvail = true;
00097         if (!timestamp.reiterate) {
00098             cacheAvail = popInternalFrame(timestamp.cacheTimestamp);
00099             if (m_function)
00100                 (*m_function)(timestamp, m_internalPose, m_nextPose, m_param);
00101         }
00102         // only compute velocity if we have a previous pose
00103         if (cacheAvail && timestamp.interpolate) {
00104             unsigned int iXu;
00105             m_velocity = diff(m_internalPose, m_nextPose, timestamp.realTimestep);
00106             for (iXu=0; iXu<6; iXu++)
00107                 m_xudot(iXu) = m_velocity(iXu);
00108         } else if (!timestamp.reiterate) {
00109             // new position is forced, no velocity as we cannot interpolate
00110             m_internalPose = m_nextPose;
00111             m_velocity = Twist::Zero();
00112             m_xudot = e_zero_vector(6);
00113             // recompute the jacobian
00114             updateJacobian();
00115         }
00116     }
00117 }
00118 
00119 void MovingFrame::pushCache(const Timestamp& timestamp)
00120 {
00121     if (!timestamp.substep && timestamp.cache)
00122         pushInternalFrame(timestamp.cacheTimestamp);
00123 }
00124 
00125 void MovingFrame::updateKinematics(const Timestamp& timestamp)
00126 {
00127     if (timestamp.interpolate) {
00128         if (timestamp.substep) {
00129             // during substepping, update the internal pose from velocity information
00130             Twist localvel = m_internalPose.M.Inverse(m_velocity);
00131             m_internalPose.Integrate(localvel, 1.0/timestamp.realTimestep);
00132         } else {
00133             m_internalPose = m_nextPose;
00134         }
00135         // m_internalPose is updated, recompute the jacobian
00136         updateJacobian();
00137     }
00138     pushCache(timestamp);
00139 }
00140 
00141 void MovingFrame::updateJacobian()
00142 {
00143     Twist m_jac;
00144     e_matrix& Ju = m_JuArray[0];
00145 
00146     //Jacobian is always identity at position on the object, 
00147     //we ust change the reference to the world.
00148     //instead of going through complicated jacobian operation, implemented direct formula
00149     Ju(1,3) = m_internalPose.p.z();
00150     Ju(2,3) = -m_internalPose.p.y();
00151     Ju(0,4) = -m_internalPose.p.z();
00152     Ju(2,4) = m_internalPose.p.x();
00153     Ju(0,5) = m_internalPose.p.y();
00154     Ju(1,5) = -m_internalPose.p.x();
00155     // remember that this object has moved
00156     m_updated = true;
00157 }
00158 
00159 }