3
\author Shin'ichiro Nakaoka
6
#include "BodyMotionEngine.h"
8
#include "BodyMotionItem.h"
9
#include <cnoid/TimeSyncItemEngineManager>
10
#include <boost/bind.hpp>
12
using namespace boost;
13
using namespace cnoid;
17
const bool TRACE_FUNCTIONS = false;
19
class BodyMotionEngine : public TimeSyncItemEngine
24
MultiValueSeqPtr qSeq;
25
MultiAffine3SeqPtr positions;
26
Vector3SeqPtr relativeZmpSeq;
27
bool calcForwardKinematics;
29
BodyMotionEngine() { }
31
bool initialize(Item* item) {
33
BodyMotionItem* bodyMotionItem;
34
MultiValueSeqItem* multiValueSeqItem;
35
MultiAffine3SeqItem* multiAffine3SeqItem;;
37
if((bodyMotionItem = dynamic_cast<BodyMotionItem*>(item))){
38
if(setBodyItem(item)){
39
qSeq = bodyMotionItem->jointPosSeq();
40
positions = bodyMotionItem->linkPosSeq();
41
if(bodyMotionItem->hasRelativeZmpSeqItem()){
42
relativeZmpSeq = bodyMotionItem->relativeZmpSeq();
46
} else if((multiValueSeqItem = dynamic_cast<MultiValueSeqItem*>(item))){
47
if(setBodyItem(item)){
48
qSeq = multiValueSeqItem->seq();
51
} else if((multiAffine3SeqItem = dynamic_cast<MultiAffine3SeqItem*>(item))){
52
if(setBodyItem(item)){
53
positions = multiAffine3SeqItem->seq();
58
calcForwardKinematics = !(positions && positions->numParts() > 1);
59
item->sigUpdated().connect(bind(&BodyMotionEngine::notifyUpdate, this));
65
bool setBodyItem(Item* item){
66
bodyItem = item->findOwnerItem<BodyItem>();
68
body = bodyItem->body();
73
virtual bool onTimeChanged(double time){
75
bool isActive = false;
79
isActive = setJointPositions(time);
82
isActive |= setLinkPositions(time);
83
if(positions->numParts() == 1){
84
body->calcForwardKinematics(); // FK from the root
89
if(calcForwardKinematics){
90
bodyItem->calcForwardKinematics();
93
isActive |= setRelativeZmp(time);
96
bodyItem->notifyKinematicStateChange(!fkDone && calcForwardKinematics);
101
static inline bool clamp(int& frame, int numFrames) {
106
} else if(frame >= numFrames){
107
frame = numFrames - 1;
113
bool setLinkPositions(double time){
115
bool isValidTime = false;
117
const int numLinks = positions->numParts();
118
const int numFrames = positions->numFrames();
119
if(numLinks > 0 && numFrames > 0){
120
int frame = positions->frameOfTime(time);
121
isValidTime = clamp(frame, numFrames);
122
for(int i=0; i < numLinks; ++i){
123
Link* link = body->link(i);
124
const Affine3& position = positions->at(frame, i);
125
link->p = position.translation();
126
link->R = position.linear();
133
bool setJointPositions(double time){
135
bool isValidTime = false;
137
const int numJoints = qSeq->numParts();
138
int frame = qSeq->frameOfTime(time);
139
const int numFrames = qSeq->numFrames();
140
if(numJoints > 0 && numFrames > 0){
141
isValidTime = clamp(frame, numFrames);
142
MultiValueSeq::View q = qSeq->frame(frame);
143
for(int i=0; i < numJoints; ++i){
144
Link* link = body->joint(i);
152
bool setRelativeZmp(double time){
154
bool isValidTime = false;
155
int frame = relativeZmpSeq->frameOfTime(time);
156
const int numFrames = relativeZmpSeq->numFrames();
158
isValidTime = clamp(frame, numFrames);
159
Link* rootLink = body->rootLink();
160
const Vector3& relativeZmp = (*relativeZmpSeq)[frame];
161
const Vector3 absZmp = rootLink->R * relativeZmp + rootLink->p;
162
bodyItem->setZmp(absZmp);
169
typedef boost::intrusive_ptr<BodyMotionEngine> BodyMotionEnginePtr;
172
TimeSyncItemEnginePtr createBodyMotionEngine(Item* sourceItem)
174
BodyMotionEnginePtr engine = new BodyMotionEngine();
175
if(!engine->initialize(sourceItem)){
183
void cnoid::initializeBodyMotionEngine(ExtensionManager& em)
185
em.timeSyncItemEngineManger().addEngineFactory(createBodyMotionEngine);