Blender V2.61 - r43446
|
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, ×tamp); 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 }