2
@author Shin'ichiro Nakaoka
5
#include "PenetrationBlocker.h"
6
#include <cnoid/ColdetModelPair>
10
using namespace cnoid;
13
const bool TRACE_FUNCTIONS = false;
18
class PenetrationBlockerImpl
21
PenetrationBlockerImpl(Link* targetLink);
24
ColdetModelPtr targetModel;
25
std::vector<ColdetModelPairPtr> coldetModelPairs;
29
Vector3 prevBlockedPosition;
30
Vector3 prevBlockedNormal;
34
// A coldet model is copied from the original one
35
ColdetModelPtr coldetModel;
37
std::vector<LinkInfo> opponentLinkInfos;
39
void addOpponentLink(Link* link);
42
bool adjust(Vector3& io_p, const Matrix3& R, const Vector3& pushDirection);
43
bool adjustSub(Vector3& io_p, const Matrix3& R, const Vector3& pushDirection);
48
PenetrationBlocker::PenetrationBlocker(Link* targetLink)
50
impl = new PenetrationBlockerImpl(targetLink);
54
PenetrationBlockerImpl::PenetrationBlockerImpl(Link* targetLink)
55
: targetLink(targetLink)
57
if(targetLink->coldetModel){
58
targetModel = new ColdetModel(*targetLink->coldetModel);
60
pPrevGiven = targetLink->p;
63
isPrevBlocked = false;
67
void PenetrationBlocker::addOpponentLink(Link* link)
69
impl->addOpponentLink(link);
73
void PenetrationBlockerImpl::addOpponentLink(Link* link)
75
if(link->coldetModel){
76
ColdetModelPtr opponendModel = new ColdetModel(*link->coldetModel);
77
coldetModelPairs.push_back(new ColdetModelPair(opponendModel, targetModel));
80
info.coldetModel = opponendModel;
81
opponentLinkInfos.push_back(info);
86
void PenetrationBlocker::setDepth(double depth)
88
impl->targetDepth = depth;
92
void PenetrationBlocker::start()
94
impl->isPrevBlocked = false;
98
bool PenetrationBlocker::adjust(Vector3& io_p, const Matrix3& R, const Vector3& pushDirection)
100
return impl->adjust(io_p, R, pushDirection);
104
bool PenetrationBlockerImpl::adjust(Vector3& io_p, const Matrix3& R, const Vector3& pushDirection)
107
if((io_p - prevBlockedPosition).dot(prevBlockedNormal) < 0.0){
108
io_p = prevBlockedPosition;
112
return adjustSub(io_p, R, pushDirection);
116
bool PenetrationBlockerImpl::adjustSub(Vector3& io_p, const Matrix3& R, const Vector3& pushDirection)
118
bool blocked = false;
119
const Vector3 s = pushDirection.normalized();
121
for(size_t i=0; i < opponentLinkInfos.size(); ++i){
122
LinkInfo& info = opponentLinkInfos[i];
123
info.coldetModel->setPosition(info.link->R, info.link->p);
127
Vector3 maxnormal(Vector3::Zero());
129
for(loop = 0; loop < 100; ++loop){
131
targetModel->setPosition(R, io_p);
133
double maxsdepth = 0.0;
134
double maxdepth = 0.0;
136
for(size_t i=0; i < coldetModelPairs.size(); ++i){
137
ColdetModelPair& modelPair = *coldetModelPairs[i];
138
const std::vector<collision_data>& cols = modelPair.detectCollisions();
139
for(size_t j=0; j < cols.size(); ++j){
140
const collision_data& col = cols[j];
141
if(col.depth > targetDepth){
142
double d = -col.n_vector.dot(s);
144
double sdepth = col.depth * d;
145
if(sdepth > maxsdepth){
147
maxdepth = col.depth;
148
maxnormal = col.n_vector;
156
io_p += (maxdepth - targetDepth) * maxnormal;
163
isPrevBlocked = blocked;
164
prevBlockedPosition = io_p;
165
prevBlockedNormal = maxnormal;