3
@author Shin'ichiro Nakaoka
6
#include "KinematicsSimulatorItem.h"
9
#include "BodyMotionItem.h"
10
#include <cnoid/ItemTreeView>
11
#include <cnoid/ItemManager>
17
using namespace cnoid;
21
const bool TRACE_FUNCTIONS = false;
29
MultiValueSeqPtr qseqRef;
31
MultiValueSeqPtr qseqResultBuf;
32
MultiValueSeqPtr qseqResult;
33
MultiAffine3SeqItemPtr rootResultItem;
34
MultiAffine3SeqPtr rootResultBuf;
35
MultiAffine3SeqPtr rootResult;
37
LinkTraverse fkTraverse;
38
vector<Link*> footLinks;
39
vector<double> footLinkOriginHeights;
41
bool initialize(BodyItemPtr bodyItem);
42
bool updatePosition(int newFrame);
43
void putResultToBuf();
44
void setBaseLink(Link* link, double originHeight);
45
void setBaseLinkByZmp(int frame);
56
KSIImpl(KinematicsSimulatorItem* self);
57
KSIImpl(KinematicsSimulatorItem* self, const KSIImpl& org);
59
bool doStartSimulation();
61
void addBody(BodyItemPtr bodyItem);
62
bool doStepSimulation();
63
double doFlushResults();
65
KinematicsSimulatorItem* self;
67
vector<BodyUnit> bodyUnits;
68
vector<BodyUnit*> bodyUnitsToPutResult;
69
vector<BodyUnit*> bodyUnitsToNotifyUpdate;
72
int frameAtLastBufferWriting;
78
void cnoid::initializeKinematicsSimulatorItem(ExtensionManager& ext)
80
ext.itemManager().registerClass<KinematicsSimulatorItem>(N_("KinematicsSimulatorItem"));
81
ext.itemManager().addCreationPanel<KinematicsSimulatorItem>();
85
bool BodyUnit::initialize(BodyItemPtr bodyItem)
88
cout << "BodyUnit::initialize()" << endl;
91
if(bodyItem->body()->isStaticModel()){
96
body = bodyItem->body()->duplicate();
99
ItemList<BodyMotionItem> motionItems = bodyItem->getSubItems<BodyMotionItem>();
100
if(!motionItems.empty()){
101
BodyMotionItemPtr motionItem;
102
// prefer the first checked item
103
for(size_t i=0; i < motionItems.size(); ++i){
104
if(ItemTreeView::mainInstance()->isItemChecked(motionItems[i])){
105
motionItem = motionItems[i];
110
motionItem = motionItems[0];
113
frameRate = motionItem->motion()->frameRate();
114
qseqRef = motionItem->jointPosSeq();
116
qseqResultBuf.reset(new MultiValueSeq(qseqResult->numParts(), 0, frameRate));
119
if(motionItem->hasRelativeZmpSeqItem()){
120
zmpSeq = motionItem->relativeZmpSeq();
123
rootResultItem = motionItem->linkPosSeqItem();
124
rootResultBuf.reset(new MultiAffine3Seq(1, 0, frameRate));
125
rootResult = motionItem->linkPosSeq();
126
rootResult->setFrameRate(frameRate);
127
rootResult->setDimension(1, 1);
130
const YamlMapping& info = *bodyItem->body()->info();
131
const YamlSequence& footLinkInfos = *info.findSequence("footLinks");
132
if(footLinkInfos.isValid()){
133
for(int i=0; i < footLinkInfos.size(); ++i){
134
const YamlMapping& footLinkInfo = *footLinkInfos[i].toMapping();
135
Link* link = body->link(footLinkInfo["link"].toString());
137
if(link && read(footLinkInfo, "soleCenter", soleCenter)){
138
footLinks.push_back(link);
139
footLinkOriginHeights.push_back(-soleCenter[2]);
144
if(!footLinks.empty()){
148
if(bodyItem->currentBaseLink()){
149
int currentBaseLinkIndex = bodyItem->currentBaseLink()->index;
150
for(size_t i=0; i < footLinks.size(); ++i){
151
Link* footLink = footLinks[i];
152
if(footLink->index == currentBaseLinkIndex){
153
setBaseLink(footLink, footLinkOriginHeights[i]);
157
setBaseLink(footLinks[0], footLinkOriginHeights[0]);
163
if(bodyItem->currentBaseLink()){
164
baseLink = body->link(bodyItem->currentBaseLink()->index);
166
baseLink = body->rootLink();
168
fkTraverse.find(baseLink, true, true);
172
Link* rootLink = body->rootLink();
173
Affine3& initialPos = rootResult->at(0, 0);
174
initialPos.translation() = rootLink->p;
175
initialPos.linear() = rootLink->R;
178
return (qseqRef != 0);
182
void BodyUnit::setBaseLink(Link* link, double originHeight)
185
cout << "BodyUnit::setBaseLink()" << endl;
190
link->p[2] = originHeight;
192
Matrix3& R = link->R;
193
Matrix3::ColXpr x = R.col(0);
194
Matrix3::ColXpr y = R.col(1);
195
Matrix3::ColXpr z = R.col(2);
197
y = z.cross(x).normalized();
200
fkTraverse.find(link, true, true);
201
fkTraverse.calcForwardKinematics();
205
void BodyUnit::setBaseLinkByZmp(int frame)
207
Link* root = body->rootLink();
208
const Vector3 zmp = root->R * zmpSeq->at(frame) + root->p;
209
int footLinkOnZmpId = -1;
210
double l2min = std::numeric_limits<double>::max();
211
for(size_t i=0; i < footLinks.size(); ++i){
212
double l2 = (footLinks[i]->p - zmp).squaredNorm();
218
if(footLinkOnZmpId >= 0 && footLinks[footLinkOnZmpId] != baseLink){
219
setBaseLink(footLinks[footLinkOnZmpId], footLinkOriginHeights[footLinkOnZmpId]);
224
bool BodyUnit::updatePosition(int newFrame)
227
cout << "BodyUnit::updatePosition()" << endl;
230
if(newFrame >= qseqRef->numFrames()){
236
const int n = std::min(body->numJoints(), qseqRef->numParts());
238
MultiValueSeq::View qRef = qseqRef->frame(frame);
239
for(int i=0; i < n; ++i){
240
body->joint(i)->q = qRef[i];
243
fkTraverse.calcForwardKinematics();
246
setBaseLinkByZmp(frame);
248
for(size_t i=0; i < footLinks.size(); ++i){
249
Link* link = footLinks[i];
250
if(link != baseLink){
251
if(link->p[2] < footLinkOriginHeights[i]){
252
setBaseLink(link, footLinkOriginHeights[i]);
261
void BodyUnit::putResultToBuf()
264
cout << "BodyUnit::putResultToBuf()" << endl;
267
const int bufFrame = rootResultBuf->numFrames();
270
qseqResultBuf->setNumFrames(bufFrame + 1);
271
MultiValueSeq::View qResultBuf = qseqResultBuf->frame(bufFrame);
272
const int n = qResultBuf.size();
273
for(int i=0; i < n; ++i){
274
qResultBuf[i] = body->joint(i)->q;
278
rootResultBuf->setNumFrames(bufFrame + 1);
279
Link* rootLink = body->rootLink();
280
Affine3& pos = rootResultBuf->at(bufFrame, 0);
281
pos.translation() = rootLink->p;
282
pos.linear() = rootLink->R;
286
bool BodyUnit::flushBuf()
289
cout << "BodyUnit::flushBuf()" << endl;
292
const int frame = rootResult->numFrames();
293
const int numBufFrames = rootResultBuf->numFrames();
295
if(numBufFrames > 0){
298
const int n = body->numJoints();
299
qseqResult->setNumFrames(frame + numBufFrames);
300
for(int i=0; i < numBufFrames; ++i){
301
MultiValueSeq::View qResult = qseqResult->frame(frame + i);
302
MultiValueSeq::View qResultBuf = qseqResultBuf->frame(i);
303
for(int j=0; j < n; ++j){
304
qResult[j] = qResultBuf[j];
307
qseqResultBuf->setNumFrames(0);
310
rootResult->setNumFrames(frame + numBufFrames);
311
for(int i=0; i < numBufFrames; ++i){
312
rootResult->at(frame + i, 0) = rootResultBuf->at(i, 0);
314
rootResultBuf->setNumFrames(0);
317
return (numBufFrames > 0);
321
KinematicsSimulatorItem::KinematicsSimulatorItem()
323
impl = new KSIImpl(this);
327
KSIImpl::KSIImpl(KinematicsSimulatorItem* self)
334
KinematicsSimulatorItem::KinematicsSimulatorItem(const KinematicsSimulatorItem& org)
335
: SimulatorItem(org),
336
impl(new KSIImpl(this, *org.impl))
342
KSIImpl::KSIImpl(KinematicsSimulatorItem* self, const KSIImpl& org)
349
KinematicsSimulatorItem::~KinematicsSimulatorItem()
355
ItemPtr KinematicsSimulatorItem::doDuplicate() const
357
return new KinematicsSimulatorItem(*this);
361
QWidget* KinematicsSimulatorItem::settingPanel()
367
bool KinematicsSimulatorItem::doStartSimulation()
369
return impl->doStartSimulation();
373
bool KSIImpl::doStartSimulation()
376
cout << "BodyUnit::doStartSimulation()" << endl;
379
bool result = setupBodies();
383
frameAtLastBufferWriting = 0;
390
bool KSIImpl::setupBodies()
393
cout << "KSIImpl::setupBodies()" << endl;
399
WorldItemPtr worldItem = self->findOwnerItem<WorldItem>();
401
ItemList<BodyItem> bodyItems = worldItem->getBodyItems();
402
for(size_t i=0; i < bodyItems.size(); ++i){
404
if(unit.initialize(bodyItems[i])){
405
bodyUnits.push_back(unit);
406
if(unit.frameRate > mainFrameRate){
407
mainFrameRate = unit.frameRate;
413
return (!bodyUnits.empty() && mainFrameRate > 0);
417
bool KinematicsSimulatorItem::doStepSimulation()
419
return impl->doStepSimulation();
423
bool KSIImpl::doStepSimulation()
426
cout << "KSIImpl::doStepSimulation()" << endl;
431
bodyUnitsToPutResult.clear();
433
for(size_t i=0; i < bodyUnits.size(); ++i){
434
BodyUnit& unit = bodyUnits[i];
435
int frame = static_cast<int>(currentFrame * unit.frameRate / mainFrameRate);
436
if(frame > unit.frame){
437
if(unit.updatePosition(frame)){
438
bodyUnitsToPutResult.push_back(&unit);
443
bool doContinue = !bodyUnitsToPutResult.empty();
448
for(size_t i=0; i < bodyUnitsToPutResult.size(); ++i){
449
bodyUnitsToPutResult[i]->putResultToBuf();
451
frameAtLastBufferWriting = currentFrame;
453
self->requestToFlushResults();
455
self->unlockResults();
462
double KinematicsSimulatorItem::doFlushResults()
464
return impl->doFlushResults();
468
double KSIImpl::doFlushResults()
471
cout << "KSIImpl::doFlushResults()" << endl;
474
bodyUnitsToNotifyUpdate.clear();
478
for(size_t i=0; i < bodyUnits.size(); ++i){
479
if(bodyUnits[i].flushBuf()){
480
bodyUnitsToNotifyUpdate.push_back(&bodyUnits[i]);
484
int frame = frameAtLastBufferWriting;
486
self->unlockResults();
488
for(size_t i=0; i < bodyUnitsToNotifyUpdate.size(); ++i){
489
bodyUnitsToNotifyUpdate[i]->rootResultItem->notifyUpdate();
492
return (frame / mainFrameRate);
496
double KinematicsSimulatorItem::doStopSimulation()
499
cout << "KinematicsSimulatorItem::doStopSimulation()" << endl;
502
return (impl->currentFrame / impl->mainFrameRate);
506
bool KinematicsSimulatorItem::store(Archive& archive)
512
bool KinematicsSimulatorItem::restore(const Archive& archive)