MovingFrame.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /** \file itasc/MovingFrame.cpp
  2. * \ingroup itasc
  3. */
  4. /*
  5. * MovingFrame.cpp
  6. *
  7. * Created on: Feb 10, 2009
  8. * Author: benoitbolsee
  9. */
  10. #include "MovingFrame.hpp"
  11. #include <string.h>
  12. namespace iTaSC{
  13. static const unsigned int frameCacheSize = (sizeof(((Frame*)0)->p.data)+sizeof(((Frame*)0)->M.data))/sizeof(double);
  14. MovingFrame::MovingFrame(const Frame& frame):UncontrolledObject(),
  15. m_function(NULL), m_param(NULL), m_velocity(), m_poseCCh(-1), m_poseCTs(0)
  16. {
  17. m_internalPose = m_nextPose = frame;
  18. initialize(6, 1);
  19. e_matrix& Ju = m_JuArray[0];
  20. Ju = e_identity_matrix(6,6);
  21. }
  22. MovingFrame::~MovingFrame()
  23. {
  24. }
  25. bool MovingFrame::finalize()
  26. {
  27. updateJacobian();
  28. return true;
  29. }
  30. void MovingFrame::initCache(Cache *_cache)
  31. {
  32. m_cache = _cache;
  33. m_poseCCh = -1;
  34. if (m_cache) {
  35. m_poseCCh = m_cache->addChannel(this,"pose",frameCacheSize*sizeof(double));
  36. // don't store the initial pose, it's causing unnecessary large velocity on the first step
  37. //pushInternalFrame(0);
  38. }
  39. }
  40. void MovingFrame::pushInternalFrame(CacheTS timestamp)
  41. {
  42. if (m_poseCCh >= 0) {
  43. double buf[frameCacheSize];
  44. memcpy(buf, m_internalPose.p.data, sizeof(m_internalPose.p.data));
  45. memcpy(&buf[sizeof(m_internalPose.p.data)/sizeof(double)], m_internalPose.M.data, sizeof(m_internalPose.M.data));
  46. m_cache->addCacheVectorIfDifferent(this, m_poseCCh, timestamp, buf, frameCacheSize, KDL::epsilon);
  47. m_poseCTs = timestamp;
  48. }
  49. }
  50. // load pose just preceding timestamp
  51. // return false if no cache position was found
  52. bool MovingFrame::popInternalFrame(CacheTS timestamp)
  53. {
  54. if (m_poseCCh >= 0) {
  55. char *item;
  56. item = (char *)m_cache->getPreviousCacheItem(this, m_poseCCh, &timestamp);
  57. if (item && m_poseCTs != timestamp) {
  58. memcpy(m_internalPose.p.data, item, sizeof(m_internalPose.p.data));
  59. item += sizeof(m_internalPose.p.data);
  60. memcpy(m_internalPose.M.data, item, sizeof(m_internalPose.M.data));
  61. m_poseCTs = timestamp;
  62. // changing the starting pose, recompute the jacobian
  63. updateJacobian();
  64. }
  65. return (item) ? true : false;
  66. }
  67. // in case of no cache, there is always a previous position
  68. return true;
  69. }
  70. bool MovingFrame::setFrame(const Frame& frame)
  71. {
  72. m_internalPose = m_nextPose = frame;
  73. return true;
  74. }
  75. bool MovingFrame::setCallback(MovingFrameCallback _function, void* _param)
  76. {
  77. m_function = _function;
  78. m_param = _param;
  79. return true;
  80. }
  81. void MovingFrame::updateCoordinates(const Timestamp& timestamp)
  82. {
  83. // don't compute the velocity during substepping, it is assumed constant.
  84. if (!timestamp.substep) {
  85. bool cacheAvail = true;
  86. if (!timestamp.reiterate) {
  87. cacheAvail = popInternalFrame(timestamp.cacheTimestamp);
  88. if (m_function)
  89. (*m_function)(timestamp, m_internalPose, m_nextPose, m_param);
  90. }
  91. // only compute velocity if we have a previous pose
  92. if (cacheAvail && timestamp.interpolate) {
  93. unsigned int iXu;
  94. m_velocity = diff(m_internalPose, m_nextPose, timestamp.realTimestep);
  95. for (iXu=0; iXu<6; iXu++)
  96. m_xudot(iXu) = m_velocity(iXu);
  97. } else if (!timestamp.reiterate) {
  98. // new position is forced, no velocity as we cannot interpolate
  99. m_internalPose = m_nextPose;
  100. m_velocity = Twist::Zero();
  101. m_xudot = e_zero_vector(6);
  102. // recompute the jacobian
  103. updateJacobian();
  104. }
  105. }
  106. }
  107. void MovingFrame::pushCache(const Timestamp& timestamp)
  108. {
  109. if (!timestamp.substep && timestamp.cache)
  110. pushInternalFrame(timestamp.cacheTimestamp);
  111. }
  112. void MovingFrame::updateKinematics(const Timestamp& timestamp)
  113. {
  114. if (timestamp.interpolate) {
  115. if (timestamp.substep) {
  116. // during substepping, update the internal pose from velocity information
  117. Twist localvel = m_internalPose.M.Inverse(m_velocity);
  118. m_internalPose.Integrate(localvel, 1.0/timestamp.realTimestep);
  119. } else {
  120. m_internalPose = m_nextPose;
  121. }
  122. // m_internalPose is updated, recompute the jacobian
  123. updateJacobian();
  124. }
  125. pushCache(timestamp);
  126. }
  127. void MovingFrame::updateJacobian()
  128. {
  129. Twist m_jac;
  130. e_matrix& Ju = m_JuArray[0];
  131. //Jacobian is always identity at position on the object,
  132. //we ust change the reference to the world.
  133. //instead of going through complicated jacobian operation, implemented direct formula
  134. Ju(1,3) = m_internalPose.p.z();
  135. Ju(2,3) = -m_internalPose.p.y();
  136. Ju(0,4) = -m_internalPose.p.z();
  137. Ju(2,4) = m_internalPose.p.x();
  138. Ju(0,5) = m_internalPose.p.y();
  139. Ju(1,5) = -m_internalPose.p.x();
  140. // remember that this object has moved
  141. m_updated = true;
  142. }
  143. }