Blender V2.61 - r43446
|
00001 00004 /* 00005 * CopyPose.cpp 00006 * 00007 * Created on: Mar 17, 2009 00008 * Author: benoit bolsee 00009 */ 00010 00011 #include "CopyPose.hpp" 00012 #include "kdl/kinfam_io.hpp" 00013 #include <math.h> 00014 #include <string.h> 00015 00016 namespace iTaSC 00017 { 00018 00019 const unsigned int maxPoseCacheSize = (2*(3+3*2)); 00020 CopyPose::CopyPose(unsigned int control_output, unsigned int dynamic_output, double armlength, double accuracy, unsigned int maximum_iterations): 00021 ConstraintSet(), 00022 m_cache(NULL), 00023 m_poseCCh(-1),m_poseCTs(0) 00024 { 00025 m_maxerror = armlength/2.0; 00026 m_outputControl = (control_output & CTL_ALL); 00027 unsigned int _nc = nBitsOn(m_outputControl); 00028 if (!_nc) 00029 return; 00030 // reset the constraint set 00031 reset(_nc, accuracy, maximum_iterations); 00032 _nc = 0; 00033 m_nvalues = 0; 00034 int nrot = 0, npos = 0; 00035 int nposCache = 0, nrotCache = 0; 00036 m_outputDynamic = (dynamic_output & m_outputControl); 00037 memset(m_values, 0, sizeof(m_values)); 00038 memset(m_posData, 0, sizeof(m_posData)); 00039 memset(m_rotData, 0, sizeof(m_rotData)); 00040 memset(&m_rot, 0, sizeof(m_rot)); 00041 memset(&m_pos, 0, sizeof(m_pos)); 00042 if (m_outputControl & CTL_POSITION) { 00043 m_pos.alpha = 1.0; 00044 m_pos.K = 20.0; 00045 m_pos.tolerance = 0.05; 00046 m_values[m_nvalues].alpha = m_pos.alpha; 00047 m_values[m_nvalues].feedback = m_pos.K; 00048 m_values[m_nvalues].tolerance = m_pos.tolerance; 00049 m_values[m_nvalues].id = ID_POSITION; 00050 if (m_outputControl & CTL_POSITIONX) { 00051 m_Wy(_nc) = m_pos.alpha/*/(m_pos.tolerance*m_pos.K)*/; 00052 m_Cf(_nc++,0)=1.0; 00053 m_posData[npos++].id = ID_POSITIONX; 00054 if (m_outputDynamic & CTL_POSITIONX) 00055 nposCache++; 00056 } 00057 if (m_outputControl & CTL_POSITIONY) { 00058 m_Wy(_nc) = m_pos.alpha/*/(m_pos.tolerance*m_pos.K)*/; 00059 m_Cf(_nc++,1)=1.0; 00060 m_posData[npos++].id = ID_POSITIONY; 00061 if (m_outputDynamic & CTL_POSITIONY) 00062 nposCache++; 00063 } 00064 if (m_outputControl & CTL_POSITIONZ) { 00065 m_Wy(_nc) = m_pos.alpha/*/(m_pos.tolerance*m_pos.K)*/; 00066 m_Cf(_nc++,2)=1.0; 00067 m_posData[npos++].id = ID_POSITIONZ; 00068 if (m_outputDynamic & CTL_POSITIONZ) 00069 nposCache++; 00070 } 00071 m_values[m_nvalues].number = npos; 00072 m_values[m_nvalues++].values = m_posData; 00073 m_pos.firsty = 0; 00074 m_pos.ny = npos; 00075 } 00076 if (m_outputControl & CTL_ROTATION) { 00077 m_rot.alpha = 1.0; 00078 m_rot.K = 20.0; 00079 m_rot.tolerance = 0.05; 00080 m_values[m_nvalues].alpha = m_rot.alpha; 00081 m_values[m_nvalues].feedback = m_rot.K; 00082 m_values[m_nvalues].tolerance = m_rot.tolerance; 00083 m_values[m_nvalues].id = ID_ROTATION; 00084 if (m_outputControl & CTL_ROTATIONX) { 00085 m_Wy(_nc) = m_rot.alpha/*/(m_rot.tolerance*m_rot.K)*/; 00086 m_Cf(_nc++,3)=1.0; 00087 m_rotData[nrot++].id = ID_ROTATIONX; 00088 if (m_outputDynamic & CTL_ROTATIONX) 00089 nrotCache++; 00090 } 00091 if (m_outputControl & CTL_ROTATIONY) { 00092 m_Wy(_nc) = m_rot.alpha/*/(m_rot.tolerance*m_rot.K)*/; 00093 m_Cf(_nc++,4)=1.0; 00094 m_rotData[nrot++].id = ID_ROTATIONY; 00095 if (m_outputDynamic & CTL_ROTATIONY) 00096 nrotCache++; 00097 } 00098 if (m_outputControl & CTL_ROTATIONZ) { 00099 m_Wy(_nc) = m_rot.alpha/*/(m_rot.tolerance*m_rot.K)*/; 00100 m_Cf(_nc++,5)=1.0; 00101 m_rotData[nrot++].id = ID_ROTATIONZ; 00102 if (m_outputDynamic & CTL_ROTATIONZ) 00103 nrotCache++; 00104 } 00105 m_values[m_nvalues].number = nrot; 00106 m_values[m_nvalues++].values = m_rotData; 00107 m_rot.firsty = npos; 00108 m_rot.ny = nrot; 00109 } 00110 assert(_nc == m_nc); 00111 m_Jf=e_identity_matrix(6,6); 00112 m_poseCacheSize = ((nrotCache)?(3+nrotCache*2):0)+((nposCache)?(3+nposCache*2):0); 00113 } 00114 00115 CopyPose::~CopyPose() 00116 { 00117 } 00118 00119 bool CopyPose::initialise(Frame& init_pose) 00120 { 00121 m_externalPose = m_internalPose = init_pose; 00122 updateJacobian(); 00123 return true; 00124 } 00125 00126 void CopyPose::modelUpdate(Frame& _external_pose,const Timestamp& timestamp) 00127 { 00128 m_internalPose = m_externalPose = _external_pose; 00129 updateJacobian(); 00130 } 00131 00132 void CopyPose::initCache(Cache *_cache) 00133 { 00134 m_cache = _cache; 00135 m_poseCCh = -1; 00136 if (m_cache) { 00137 // create one channel for the coordinates 00138 m_poseCCh = m_cache->addChannel(this, "Xf", m_poseCacheSize*sizeof(double)); 00139 // don't save initial value, it will be recomputed from external pose 00140 //pushPose(0); 00141 } 00142 } 00143 00144 double* CopyPose::pushValues(double* item, ControlState* _state, unsigned int mask) 00145 { 00146 ControlState::ControlValue* _yval; 00147 int i; 00148 00149 *item++ = _state->alpha; 00150 *item++ = _state->K; 00151 *item++ = _state->tolerance; 00152 00153 for (i=0, _yval=_state->output; i<_state->ny; mask<<=1) { 00154 if (m_outputControl & mask) { 00155 if (m_outputDynamic & mask) { 00156 *item++ = _yval->yd; 00157 *item++ = _yval->yddot; 00158 } 00159 _yval++; 00160 i++; 00161 } 00162 } 00163 return item; 00164 } 00165 00166 void CopyPose::pushPose(CacheTS timestamp) 00167 { 00168 if (m_poseCCh >= 0) { 00169 if (m_poseCacheSize) { 00170 double buf[maxPoseCacheSize]; 00171 double *item = buf; 00172 if (m_outputDynamic & CTL_POSITION) 00173 item = pushValues(item, &m_pos, CTL_POSITIONX); 00174 if (m_outputDynamic & CTL_ROTATION) 00175 item = pushValues(item, &m_rot, CTL_ROTATIONX); 00176 m_cache->addCacheVectorIfDifferent(this, m_poseCCh, timestamp, buf, m_poseCacheSize, KDL::epsilon); 00177 } else 00178 m_cache->addCacheVectorIfDifferent(this, m_poseCCh, timestamp, NULL, 0, KDL::epsilon); 00179 m_poseCTs = timestamp; 00180 } 00181 } 00182 00183 double* CopyPose::restoreValues(double* item, ConstraintValues* _values, ControlState* _state, unsigned int mask) 00184 { 00185 ConstraintSingleValue* _data; 00186 ControlState::ControlValue* _yval; 00187 int i, j; 00188 00189 _values->alpha = _state->alpha = *item++; 00190 _values->feedback = _state->K = *item++; 00191 _values->tolerance = _state->tolerance = *item++; 00192 00193 for (i=_state->firsty, j=i+_state->ny, _yval=_state->output, _data=_values->values; i<j; mask<<=1) { 00194 if (m_outputControl & mask) { 00195 m_Wy(i) = _state->alpha/*/(_state->tolerance*_state->K)*/; 00196 if (m_outputDynamic & mask) { 00197 _data->yd = _yval->yd = *item++; 00198 _data->yddot = _yval->yddot = *item++; 00199 } 00200 _data++; 00201 _yval++; 00202 i++; 00203 } 00204 } 00205 return item; 00206 } 00207 00208 bool CopyPose::popPose(CacheTS timestamp) 00209 { 00210 bool found = false; 00211 if (m_poseCCh >= 0) { 00212 double *item = (double*)m_cache->getPreviousCacheItem(this, m_poseCCh, ×tamp); 00213 if (item) { 00214 found = true; 00215 if (timestamp != m_poseCTs) { 00216 int i=0; 00217 if (m_outputControl & CTL_POSITION) { 00218 if (m_outputDynamic & CTL_POSITION) { 00219 item = restoreValues(item, &m_values[i], &m_pos, CTL_POSITIONX); 00220 } 00221 i++; 00222 } 00223 if (m_outputControl & CTL_ROTATION) { 00224 if (m_outputDynamic & CTL_ROTATION) { 00225 item = restoreValues(item, &m_values[i], &m_rot, CTL_ROTATIONX); 00226 } 00227 i++; 00228 } 00229 m_poseCTs = timestamp; 00230 item = NULL; 00231 } 00232 } 00233 } 00234 return found; 00235 } 00236 00237 void CopyPose::interpolateOutput(ControlState* _state, unsigned int mask, const Timestamp& timestamp) 00238 { 00239 ControlState::ControlValue* _yval; 00240 int i; 00241 00242 for (i=0, _yval=_state->output; i<_state->ny; mask <<= 1) { 00243 if (m_outputControl & mask) { 00244 if (m_outputDynamic & mask) { 00245 if (timestamp.substep && timestamp.interpolate) { 00246 _yval->yd += _yval->yddot*timestamp.realTimestep; 00247 } else { 00248 _yval->yd = _yval->nextyd; 00249 _yval->yddot = _yval->nextyddot; 00250 } 00251 } 00252 i++; 00253 _yval++; 00254 } 00255 } 00256 } 00257 00258 void CopyPose::pushCache(const Timestamp& timestamp) 00259 { 00260 if (!timestamp.substep && timestamp.cache) { 00261 pushPose(timestamp.cacheTimestamp); 00262 } 00263 } 00264 00265 void CopyPose::updateKinematics(const Timestamp& timestamp) 00266 { 00267 if (timestamp.interpolate) { 00268 if (m_outputDynamic & CTL_POSITION) 00269 interpolateOutput(&m_pos, CTL_POSITIONX, timestamp); 00270 if (m_outputDynamic & CTL_ROTATION) 00271 interpolateOutput(&m_rot, CTL_ROTATIONX, timestamp); 00272 } 00273 pushCache(timestamp); 00274 } 00275 00276 void CopyPose::updateJacobian() 00277 { 00278 //Jacobian is always identity at the start of the constraint chain 00279 //instead of going through complicated jacobian operation, implemented direct formula 00280 //m_Jf(1,3) = m_internalPose.p.z(); 00281 //m_Jf(2,3) = -m_internalPose.p.y(); 00282 //m_Jf(0,4) = -m_internalPose.p.z(); 00283 //m_Jf(2,4) = m_internalPose.p.x(); 00284 //m_Jf(0,5) = m_internalPose.p.y(); 00285 //m_Jf(1,5) = -m_internalPose.p.x(); 00286 } 00287 00288 void CopyPose::updateState(ConstraintValues* _values, ControlState* _state, unsigned int mask, double timestep) 00289 { 00290 unsigned int id = (mask == CTL_ROTATIONX) ? ID_ROTATIONX : ID_POSITIONX; 00291 ControlState::ControlValue* _yval; 00292 ConstraintSingleValue* _data; 00293 int i, j, k; 00294 int action = 0; 00295 00296 if ((_values->action & ACT_ALPHA) && _values->alpha >= 0.0) { 00297 _state->alpha = _values->alpha; 00298 action |= ACT_ALPHA; 00299 } 00300 if ((_values->action & ACT_TOLERANCE) && _values->tolerance > KDL::epsilon) { 00301 _state->tolerance = _values->tolerance; 00302 action |= ACT_TOLERANCE; 00303 } 00304 if ((_values->action & ACT_FEEDBACK) && _values->feedback > KDL::epsilon) { 00305 _state->K = _values->feedback; 00306 action |= ACT_FEEDBACK; 00307 } 00308 for (i=_state->firsty, j=_state->firsty+_state->ny, _yval=_state->output; i<j; mask <<= 1, id++) { 00309 if (m_outputControl & mask) { 00310 if (action) 00311 m_Wy(i) = _state->alpha/*/(_state->tolerance*_state->K)*/; 00312 // check if this controlled output is provided 00313 for (k=0, _data=_values->values; k<_values->number; k++, _data++) { 00314 if (_data->id == id) { 00315 switch (_data->action & (ACT_VALUE|ACT_VELOCITY)) { 00316 case 0: 00317 // no indication, keep current values 00318 break; 00319 case ACT_VELOCITY: 00320 // only the velocity is given estimate the new value by integration 00321 _data->yd = _yval->yd+_data->yddot*timestep; 00322 // walkthrough 00323 case ACT_VALUE: 00324 _yval->nextyd = _data->yd; 00325 // if the user sets the value, we assume future velocity is zero 00326 // (until the user changes the value again) 00327 _yval->nextyddot = (_data->action & ACT_VALUE) ? 0.0 : _data->yddot; 00328 if (timestep>0.0) { 00329 _yval->yddot = (_data->yd-_yval->yd)/timestep; 00330 } else { 00331 // allow the user to change target instantenously when this function 00332 // if called from setControlParameter with timestep = 0 00333 _yval->yd = _yval->nextyd; 00334 _yval->yddot = _yval->nextyddot; 00335 } 00336 break; 00337 case (ACT_VALUE|ACT_VELOCITY): 00338 // the user should not set the value and velocity at the same time. 00339 // In this case, we will assume that he wants to set the future value 00340 // and we compute the current value to match the velocity 00341 _yval->yd = _data->yd - _data->yddot*timestep; 00342 _yval->nextyd = _data->yd; 00343 _yval->nextyddot = _data->yddot; 00344 if (timestep>0.0) { 00345 _yval->yddot = (_data->yd-_yval->yd)/timestep; 00346 } else { 00347 _yval->yd = _yval->nextyd; 00348 _yval->yddot = _yval->nextyddot; 00349 } 00350 break; 00351 } 00352 } 00353 } 00354 _yval++; 00355 i++; 00356 } 00357 } 00358 } 00359 00360 00361 bool CopyPose::setControlParameters(struct ConstraintValues* _values, unsigned int _nvalues, double timestep) 00362 { 00363 while (_nvalues > 0) { 00364 if (_values->id >= ID_POSITION && _values->id <= ID_POSITIONZ && (m_outputControl & CTL_POSITION)) { 00365 updateState(_values, &m_pos, CTL_POSITIONX, timestep); 00366 } 00367 if (_values->id >= ID_ROTATION && _values->id <= ID_ROTATIONZ && (m_outputControl & CTL_ROTATION)) { 00368 updateState(_values, &m_rot, CTL_ROTATIONX, timestep); 00369 } 00370 _values++; 00371 _nvalues--; 00372 } 00373 return true; 00374 } 00375 00376 void CopyPose::updateValues(Vector& vel, ConstraintValues* _values, ControlState* _state, unsigned int mask) 00377 { 00378 ConstraintSingleValue* _data; 00379 ControlState::ControlValue* _yval; 00380 int i, j; 00381 00382 _values->action = 0; 00383 00384 for (i=_state->firsty, j=0, _yval=_state->output, _data=_values->values; j<3; j++, mask<<=1) { 00385 if (m_outputControl & mask) { 00386 *(double*)&_data->y = vel(j); 00387 *(double*)&_data->ydot = m_ydot(i); 00388 _data->yd = _yval->yd; 00389 _data->yddot = _yval->yddot; 00390 _data->action = 0; 00391 i++; 00392 _data++; 00393 _yval++; 00394 } 00395 } 00396 } 00397 00398 void CopyPose::updateOutput(Vector& vel, ControlState* _state, unsigned int mask) 00399 { 00400 ControlState::ControlValue* _yval; 00401 int i, j; 00402 double coef=1.0; 00403 if (mask & CTL_POSITION) { 00404 // put a limit on position error 00405 double len=0.0; 00406 for (j=0, _yval=_state->output; j<3; j++) { 00407 if (m_outputControl & (mask<<j)) { 00408 len += KDL::sqr(_yval->yd-vel(j)); 00409 _yval++; 00410 } 00411 } 00412 len = KDL::sqrt(len); 00413 if (len > m_maxerror) 00414 coef = m_maxerror/len; 00415 } 00416 for (i=_state->firsty, j=0, _yval=_state->output; j<3; j++) { 00417 if (m_outputControl & (mask<<j)) { 00418 m_ydot(i)=_yval->yddot+_state->K*coef*(_yval->yd-vel(j)); 00419 _yval++; 00420 i++; 00421 } 00422 } 00423 } 00424 00425 void CopyPose::updateControlOutput(const Timestamp& timestamp) 00426 { 00427 //IMO this should be done, no idea if it is enough (wrt Distance impl) 00428 Twist y = diff(F_identity, m_internalPose); 00429 bool found = true; 00430 if (!timestamp.substep) { 00431 if (!timestamp.reiterate) { 00432 found = popPose(timestamp.cacheTimestamp); 00433 } 00434 } 00435 if (m_constraintCallback && (m_substep || (!timestamp.reiterate && !timestamp.substep))) { 00436 // initialize first callback the application to get the current values 00437 int i=0; 00438 if (m_outputControl & CTL_POSITION) { 00439 updateValues(y.vel, &m_values[i++], &m_pos, CTL_POSITIONX); 00440 } 00441 if (m_outputControl & CTL_ROTATION) { 00442 updateValues(y.rot, &m_values[i++], &m_rot, CTL_ROTATIONX); 00443 } 00444 if ((*m_constraintCallback)(timestamp, m_values, m_nvalues, m_constraintParam)) { 00445 setControlParameters(m_values, m_nvalues, (found && timestamp.interpolate)?timestamp.realTimestep:0.0); 00446 } 00447 } 00448 if (m_outputControl & CTL_POSITION) { 00449 updateOutput(y.vel, &m_pos, CTL_POSITIONX); 00450 } 00451 if (m_outputControl & CTL_ROTATION) { 00452 updateOutput(y.rot, &m_rot, CTL_ROTATIONX); 00453 } 00454 } 00455 00456 const ConstraintValues* CopyPose::getControlParameters(unsigned int* _nvalues) 00457 { 00458 Twist y = diff(m_internalPose,F_identity); 00459 int i=0; 00460 if (m_outputControl & CTL_POSITION) { 00461 updateValues(y.vel, &m_values[i++], &m_pos, CTL_POSITIONX); 00462 } 00463 if (m_outputControl & CTL_ROTATION) { 00464 updateValues(y.rot, &m_values[i++], &m_rot, CTL_ROTATIONX); 00465 } 00466 if (_nvalues) 00467 *_nvalues=m_nvalues; 00468 return m_values; 00469 } 00470 00471 double CopyPose::getMaxTimestep(double& timestep) 00472 { 00473 // CopyPose should not have any limit on linear velocity: 00474 // in case the target is out of reach, this can be very high. 00475 // We will simply limit on rotation 00476 e_scalar maxChidot = m_chidot.block(3,0,3,1).array().abs().maxCoeff(); 00477 if (timestep*maxChidot > m_maxDeltaChi) { 00478 timestep = m_maxDeltaChi/maxChidot; 00479 } 00480 return timestep; 00481 } 00482 00483 }