00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <robot/sim/SimulatedSerialManipulator>
00026
00027 #include <base/Vector3>
00028 #include <base/Orient>
00029 #include <base/Transform>
00030 #include <base/Externalizer>
00031
00032 #include <gfx/Color3>
00033 #include <gfx/Line3>
00034 #include <gfx/Segment3>
00035 #include <physics/BoundingBox>
00036 #include <physics/Material>
00037 #include <physics/Box>
00038 #include <physics/Sphere>
00039 #include <physics/Capsule>
00040 #include <physics/Solid>
00041 #include <physics/ConstraintGroup>
00042 #include <physics/Joint>
00043 #include <physics/HingeJoint>
00044 #include <physics/SliderJoint>
00045 #include <physics/Motor>
00046 #include <physics/CollisionCuller>
00047 #include <physics/CollisionDetector>
00048 #include <physics/CollisionState>
00049 #include <physics/NullCollisionResponseHandler>
00050 #include <physics/SpatialTransform>
00051
00052 #include <physics/VisualDebugUtil>
00053
00054 #include <robot/KinematicChain>
00055
00056
00057 using robot::sim::SimulatedSerialManipulator;
00058
00059 using base::Point3;
00060 using base::Orient;
00061 using base::Dimension3;
00062 using base::Transform;
00063 using gfx::Line3;
00064 using gfx::Segment3;
00065 using gfx::Color4;
00066 using physics::BoundingBox;
00067 using physics::Collidable;
00068 using physics::CollidableBody;
00069 using physics::CollidableGroup;
00070 using physics::CollisionState;
00071 using physics::CollisionCuller;
00072 using physics::CollisionDetector;
00073 using physics::CollisionResponseHandler;
00074 using physics::NullCollisionResponseHandler;
00075 using physics::Shape;
00076 using physics::Box;
00077 using physics::Sphere;
00078 using physics::Capsule;
00079 using physics::Material;
00080 using physics::Solid;
00081 using physics::SpatialGroup;
00082 using physics::SpatialTransform;
00083 using physics::ConstraintGroup;
00084 using physics::Joint;
00085 using physics::HingeJoint;
00086 using physics::SliderJoint;
00087 using physics::Motor;
00088
00089 using physics::VisualDebugUtil;
00090
00091 using robot::KinematicChain;
00092 using robot::sim::SimulatedManipulatorDescription;
00093 using robot::sim::SimulatedKinematicChain;
00094 using robot::sim::SimulatedTool;
00095
00096
00097 #include <physics/ODESolidConnectedCollidableBody>
00098 using physics::SolidConnectedCollidableBody;
00099 using physics::ODESolidConnectedCollidableBody;
00100
00101
00102 #include <ode/ode.h>
00103 #include <ode/rotation.h>
00104
00105
00106 SimulatedSerialManipulator::SimulatedSerialManipulator(bool dynamic)
00107 : SimulatedKinematicChain(dynamic), proximityDistance(0.05), proximityAngle(Math::degToRad(3)), toolGrasped(false)
00108 {
00109 }
00110
00111 SimulatedSerialManipulator::SimulatedSerialManipulator(ref<physics::SolidSystem> solidSystem, bool dynamic)
00112 : SimulatedKinematicChain(solidSystem, dynamic), proximityDistance(0.05), proximityAngle(Math::degToRad(3)), toolGrasped(false)
00113 {
00114 }
00115
00116 SimulatedSerialManipulator::SimulatedSerialManipulator(ref<const robot::ManipulatorDescription> manipulatorDescription, ref<physics::SolidSystem> solidSystem, bool dynamic)
00117 : SimulatedKinematicChain(solidSystem,dynamic),
00118 proximityDistance(0.05), proximityAngle(Math::degToRad(3)), toolGrasped(false)
00119 {
00120 if (instanceof(*manipulatorDescription, const SimulatedManipulatorDescription))
00121 manipulatorDescr = narrow_ref<const SimulatedManipulatorDescription>(manipulatorDescription);
00122 else
00123 manipulatorDescr = ref<SimulatedManipulatorDescription>(NewObj SimulatedManipulatorDescription(*manipulatorDescription));
00124
00125 chain = manipulatorDescr->getKinematicChain();
00126 q.reset(manipulatorDescr->initialConfiguration());
00127 }
00128
00129
00130
00131 bool SimulatedSerialManipulator::formatSupported(String format, Real version, ExternalizationType type) const
00132 {
00133 return false;
00134 }
00135
00136 void SimulatedSerialManipulator::externalize(base::Externalizer& e, String format, Real version)
00137 {
00138 if (format == "") format = "xml";
00139
00140 if (!formatSupported(format,version,e.ioType()))
00141 throw std::invalid_argument(Exception(String("format ")+format+" v"+base::realToString(version)+" unsupported"));
00142
00143
00144 manipulatorDescr->externalize(e,format,version);
00145 }
00146
00147
00148
00149 void SimulatedSerialManipulator::setJointForce(Int j, Real f)
00150 {
00151 Assertm((j>=1)&&(j<=chain.dof()), "joint index in range");
00152
00153 if (!dynamic) return;
00154
00155 ref<Motor> motor(joints[j-1]->getMotor(1));
00156 motor->setTargetVel( (f>0)?10:-10 );
00157 motor->setMaxForce(f);
00158 }
00159
00160 void SimulatedSerialManipulator::setJointVel(Int j, Real v, Real maxForce)
00161 {
00162 Assertm((j>=1)&&(j<=chain.dof()), "joint index in range");
00163
00164 if (!dynamic) return;
00165
00166 ref<Motor> motor(joints[j-1]->getMotor(1));
00167 motor->setTargetVel(v);
00168 motor->setMaxForce(maxForce);
00169 }
00170
00171
00172 void SimulatedSerialManipulator::setJointPos(Int j, Real p)
00173 {
00174 Assertm((j>=1)&&(j<=chain.dof()), "joint index in range");
00175
00176 q[j-1] = p;
00177
00178
00179
00180
00181 Transform baseTransform(manipulatorDescr->getBaseTransform());
00182 mountConfiguration = inverse(baseTransform)*linkGroups[0]->getConfiguration();
00183
00184 TransformInfo transformInfo( computeLinkTransforms(mountConfiguration, q) );
00185 positionLinks(transformInfo);
00186
00187
00188 if (toolGrasped) {
00189 Transform eeConfig( getEEPosition(), getEEOrientation() );
00190 proximityTool->setConfiguration( eeConfig );
00191 }
00192
00193 }
00194
00195
00196 Real SimulatedSerialManipulator::getJointPos(Int j) const
00197 {
00198 Assertm((j>=1)&&(j<=chain.dof()), "joint index in range");
00199
00200 if (dynamic) {
00201
00202
00203
00204
00205
00206 if (chain[j-1].type() == KinematicChain::Link::Revolute) {
00207
00208 ref<HingeJoint> hinge(narrow_ref<HingeJoint>(joints[j-1]));
00209
00210 q[j-1] = hinge->getAngle();
00211
00212 } else {
00213 ref<SliderJoint> slider(narrow_ref<SliderJoint>(joints[j-1]));
00214 q[j-1] = slider->getPosition();
00215 }
00216
00217 } else {
00218
00219
00220
00221
00222
00223
00224 }
00225
00226 return q[j-1];
00227
00228 }
00229
00230
00231 Real SimulatedSerialManipulator::getJointVel(Int j) const
00232 {
00233 Assertm((j>=1)&&(j<=chain.dof()), "joint index in range");
00234
00235 if (!dynamic) return 0;
00236
00237 if (chain[j-1].type() == KinematicChain::Link::Revolute) {
00238
00239 ref<HingeJoint> hinge(narrow_ref<HingeJoint>(joints[j-1]));
00240 return hinge->getAngleRate();
00241 }
00242 else {
00243
00244 ref<SliderJoint> slider(narrow_ref<SliderJoint>(joints[j-1]));
00245 return slider->getPositionRate();
00246 }
00247
00248 }
00249
00250
00251
00252
00253
00254
00255 array<base::Dimension3> SimulatedSerialManipulator::computeLinkDimensions(const array<Real>& linkRadii)
00256 {
00257
00258 array<Dimension3> dim( SimulatedKinematicChain::computeLinkDimensions(linkRadii) );
00259
00260 Matrix4 baseTransform(manipulatorDescr->getBaseTransform());
00261 Real len = baseTransform.column(4).toVector3().length();
00262
00263 linkLengths[0] = len;
00264
00265 Real zl=len*0.98;
00266 if (Math::equals(len,0)) zl=0.05;
00267
00268 Real yz;
00269 if (linkRadii.size() >= 1)
00270 yz = linkRadii[0]*2.0;
00271 else
00272 yz = Math::maximum(0.05,zl*0.14);
00273
00274 dim[0] = Dimension3(yz,yz,zl);
00275
00276 return dim;
00277 }
00278
00279
00280
00281
00282
00283 SimulatedSerialManipulator::TransformInfo SimulatedSerialManipulator::computeLinkTransforms(const Transform& mountTransform, const base::Vector& q) const
00284 {
00285 TransformInfo transformInfo;
00286 transformInfo.mountTransform = mountTransform;
00287 transformInfo.q.reset(q);
00288
00289 array<Transform>& A(transformInfo.A);
00290 array<Transform>& T(transformInfo.T);
00291 array<Transform>& SLT(transformInfo.SLT);
00292 A.resize(chain.size()+1);
00293 T.resize(A.size());
00294 SLT.resize(A.size());
00295
00296 Transform baseTransform(manipulatorDescr->getBaseTransform());
00297
00298 A[0] = transformInfo.mountTransform * baseTransform;
00299 T[0] = A[0];
00300 Int j=0;
00301
00302
00303
00304 SLT[0] = Transform(Vector3(0,0,-linkLengths[0]/2.0));
00305
00306
00307
00308
00309 Vector3 localZAxis(Vector3(0,0,1));
00310 Vector3 baseOffset(baseTransform.getTranslation());
00311 if (!Math::equals(baseOffset.norm(),0)) {
00312
00313 Vector3 baseZAxis( baseOffset.normalize());
00314 Vector3 rotAxis = cross(localZAxis, baseZAxis);
00315 if (!rotAxis.equals(Vector3(0,0,0))) {
00316 Real rotAngle = Math::acos(dot(localZAxis, baseZAxis));
00317
00318 Transform R = Quat4(rotAxis, rotAngle);
00319 SLT[0] = R * SLT[0];
00320 }
00321 }
00322
00323 transformInfo.mountToBaseSolid = inverse(SLT[0]);
00324
00325
00326
00327
00328 for (Int l=1; l<=chain.size(); l++) {
00329
00330 const KinematicChain::Link& link(chain[l-1]);
00331
00332
00333
00334 Vector lq(link.dof());
00335 if (lq.size()>0)
00336 lq[0] = transformInfo.q[j];
00337 A[l] = base::toMatrix4(link.kinematicTransform(lq));
00338
00339
00340
00341 T[l] = T[l-1]*A[l];
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 SLT[l] = Quat4(Vector3(0,1,0),consts::Pi/2.0) * Transform(Vector3(0,0,-linkLengths[l]/2.0));
00352
00353 if (link.isDHType()) {
00354
00355
00356
00357
00358
00359
00360
00361
00362 Real d = (link.type() == KinematicChain::Link::Prismatic)?lq[0]:link.getD();
00363 Real incline = ( !Math::equals(d,0) && !Math::equals(linkLengths[l],0) )?
00364 Math::asin(d/linkLengths[l]) : 0;
00365 if (!Math::equals(incline,0)) {
00366 Transform rotYl = Quat4(Vector3(0,1,0),-incline);
00367 Transform rotXl = Quat4(Vector3(1,0,0), link.getAlpha());
00368 Transform rotXlInv = Quat4(Vector3(1,0,0),-link.getAlpha());
00369 Transform rotYlm1 = rotXlInv * rotYl * rotXl;
00370
00371 SLT[l] = rotYlm1 * SLT[l];
00372 }
00373
00374 }
00375
00376 if (l==chain.size())
00377 transformInfo.eeToEESolid = inverse(SLT[l]);
00378
00379 j += link.dof();
00380 }
00381
00382
00383 return transformInfo;
00384 }
00385
00386
00387
00388
00389
00390 void SimulatedSerialManipulator::createLinks(const array<base::Dimension3>& linkDims)
00391 {
00392
00393
00394
00395
00396 Assert(chain.size() > 0);
00397
00398 links.resize(chain.size()+1);
00399
00400 for (Int l=0; l<=chain.size(); l++) {
00401 const Dimension3& dim(linkDims[l]);
00402
00403 ref<Capsule> cap(NewObj Capsule(dim.z, dim.x/2.0));
00404 ref<Material> material(NewObj physics::Material());
00405
00406
00407 switch (l%10) {
00408 case 0: material->setBaseColor(gfx::Color3(0.6,0.6,0.6)); break;
00409 case 1: material->setBaseColor(gfx::Color3(0,1,0)); break;
00410 case 2: material->setBaseColor(gfx::Color3(0+0.1,1-0.1,0+0.1)); break;
00411 case 3: material->setBaseColor(gfx::Color3(0+0.2,1-0.2,0+0.2)); break;
00412 case 4: material->setBaseColor(gfx::Color3(0+0.3,1-0.3,0+0.3)); break;
00413 case 5: material->setBaseColor(gfx::Color3(0+0.4,1-0.4,0+0.4)); break;
00414 case 6: material->setBaseColor(gfx::Color3(0+0.5,1-0.5,0+0.5)); break;
00415 case 7: material->setBaseColor(gfx::Color3(0+0.6,1-0.6,0+0.6)); break;
00416 case 8: material->setBaseColor(gfx::Color3(1,1,1)); break;
00417 case 9: material->setBaseColor(gfx::Color3(1,0,0)); break;
00418 default:
00419 material->setBaseColor(gfx::Color3(0,0,1));
00420 }
00421
00422
00423 links[l] = solidSystem->createSolid(cap,material);
00424 links[l]->setName(getManipulatorDescription()->getName()+" "
00425 +String("link ")+base::intToString(l));
00426 solidSystem->addSolid(links[l]);
00427
00428
00429
00430
00431 ref<SpatialTransform> linkTransform( NewObj SpatialTransform() );
00432 linkTransform->setChild( links[l] );
00433 ref<SpatialGroup> linkGroup( NewObj SpatialGroup() );
00434 linkGroup->add(linkTransform);
00435 linkGroup->setImplicitConfiguration(linkTransform);
00436 if (l > 0) linkGroups[l-1]->add(linkGroup);
00437 linkGroups.push_back(linkGroup);
00438
00439 if (l == 0)
00440 baseSolid = links[l];
00441 else
00442 if (l == chain.size())
00443 endSolid = links[l];
00444 }
00445 }
00446
00447
00448
00449 void SimulatedSerialManipulator::positionLinks(const SimulatedSerialManipulator::TransformInfo& transformInfo)
00450 {
00451 Assert(links.size() == chain.size()+1);
00452
00453
00454
00455 mountToBaseSolid = transformInfo.mountToBaseSolid;
00456 eeToEESolid = transformInfo.eeToEESolid;
00457
00458
00459
00460 const array<Transform>& SLT( transformInfo.SLT );
00461 const array<Transform>& T( transformInfo.T );
00462
00463
00464
00465 for (Int l=0; l<=chain.size(); l++) {
00466
00467 ref<SpatialGroup> linkGroup(linkGroups[l]);
00468 SpatialGroup::iterator firstChild = linkGroup->begin();
00469
00470
00471
00472 ref<SpatialTransform> linkSpatialTransform( narrow_ref<SpatialTransform>( *firstChild ) );
00473 linkSpatialTransform->setTransform( SLT[l] );
00474
00475
00476 linkSpatialTransform->setConfiguration( T[l] );
00477
00478 }
00479
00480 }
00481
00482
00483
00484 void SimulatedSerialManipulator::disableCollisions(const array<ref<physics::Collidable> >& collidables,
00485 const array<ref<physics::Collidable> >& proximityCollidables)
00486 {
00487 Assert(solidSystem);
00488 Assert(links.size() == chain.size()+1);
00489
00490 ref<CollisionCuller> cc(solidSystem->getCollisionCuller());
00491 bool hasProxSensors = manipulatorDescr->hasLinkProximitySensors();
00492
00493 bool disableNextWithPrev = false;
00494
00495
00496 for (Int l=1; l<=chain.size(); l++) {
00497
00498 cc->collisionEnable(false,collidables[l-1],collidables[l]);
00499
00500
00501 if (hasProxSensors) {
00502 cc->collisionEnable(false,collidables[l], proximityCollidables[l]);
00503
00504 cc->collisionEnable(false,collidables[l-1],proximityCollidables[l]);
00505 cc->collisionEnable(false,proximityCollidables[l-1],collidables[l]);
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 for(Int pl=0; pl<proximityCollidables.size(); pl++)
00520 cc->collisionEnable(false,collidables[l], proximityCollidables[pl]);
00521
00522 }
00523
00524 if (disableNextWithPrev) {
00525 cc->collisionEnable(false,collidables[l-2],collidables[l]);
00526 if (hasProxSensors) cc->collisionEnable(false,collidables[l-2],proximityCollidables[l]);
00527 disableNextWithPrev = false;
00528 }
00529
00530 if (linkLengths[l]<=0.05)
00531 disableNextWithPrev = true;
00532
00533 }
00534
00535
00536 if (hasProxSensors)
00537 for(Int pl=0; pl<proximityCollidables.size(); pl++)
00538 cc->collisionEnable(false,collidables[0], proximityCollidables[pl]);
00539
00540 }
00541
00542
00543 void SimulatedSerialManipulator::attachJoints(const SimulatedSerialManipulator::TransformInfo& transformInfo)
00544 {
00545 if (links.size() < 2) return;
00546
00547
00548 const array<Transform>& T( transformInfo.T );
00549 const array<Transform>& SLT( transformInfo.SLT );
00550
00551 ref<ConstraintGroup> cgroup = solidSystem->createConstraintGroup();
00552 solidSystem->addConstraintGroup(cgroup);
00553 ref<Motor> motor;
00554 joints.resize(links.size()-1);
00555
00556 for (Int l=1; l<links.size(); l++) {
00557
00558
00559 const KinematicChain::Link& link(chain[l-1]);
00560 ref<Joint> joint;
00561
00562
00563 if (link.isDHType()) {
00564
00565
00566
00567
00568
00569 Vector3 axis( Vector3(-1,0,0) );
00570 if (l>1) {
00571 axis = (T[l-1]*SLT[l-1]).rotate(axis);
00572 axis = inverse(T[l]*SLT[l]).rotate(axis);
00573 } else {
00574 axis = T[0].rotate(Vector3(0,0,1));
00575 axis = inverse(T[1]*SLT[1]).rotate(axis);
00576 }
00577
00578
00579 if (link.type() == KinematicChain::Link::Revolute) {
00580
00581 ref<HingeJoint> hinge = solidSystem->createHingeJoint();
00582 joint = hinge;
00583 cgroup->addConstraint(hinge);
00584 joints[l-1] = joint;
00585 Assert(links[l-1]);
00586 joint->attach(links[l], links[l-1]);
00587
00588
00589 hinge->setAnchor( Point3(0,0,-linkLengths[l]/2) );
00590 hinge->setAxis( axis );
00591
00592
00593 if (! ((link.minLimit() <= -consts::Pi)&&(link.maxLimit() >= consts::Pi)) ) {
00594 hinge->setLowStop(link.minLimit() - Math::degToRad(1) );
00595 hinge->setHighStop(link.maxLimit() + Math::degToRad(1) );
00596 hinge->setStopRestitution(0.2);
00597 }
00598
00599
00600 motor = solidSystem->createMotor();
00601 hinge->attachMotor(1, motor);
00602
00603 }
00604 else if (link.type() == KinematicChain::Link::Prismatic) {
00605
00606 ref<SliderJoint> slider = solidSystem->createSliderJoint();
00607 joint = slider;
00608 cgroup->addConstraint(slider);
00609 joints[l-1] = joint;
00610 Assert(links[l-1]);
00611 joint->attach(links[l], links[l-1]);
00612
00613 slider->setAxis( axis );
00614
00615
00616 slider->setLowStop(link.minLimit());
00617 slider->setHighStop(link.maxLimit());
00618 slider->setStopRestitution(0.2);
00619
00620
00621 motor = solidSystem->createMotor();
00622 slider->attachMotor(1, motor);
00623
00624 Logln("Warning: Prismatic joints not fully implemented");
00625 }
00626 }
00627 else
00628 throw std::invalid_argument(Exception("unknown/unsupported joint type: " + link.type()));
00629
00630 motor->setTargetVel(0);
00631 motor->setMaxForce(0.001);
00632
00633 }
00634
00635 }
00636
00637
00638
00639 void SimulatedSerialManipulator::construct(const base::Point3& initialPosition,
00640 const base::Orient& initialOrientation)
00641 {
00642 mountConfiguration = Transform(initialPosition, initialOrientation);
00643
00644 linkGroups.clear();
00645 createLinks(computeLinkDimensions(manipulatorDescr->getLinkRadii()));
00646
00647
00648
00649
00650 Assert(chain.size() > 0);
00651 Vector q(chain.dof());
00652
00653
00654 for(Int j=0; j<chain.dof(); j++) {
00655 const KinematicChain::Link& link(chain.linkOfVariable(j));
00656 q[j] = link.variable();
00657 }
00658
00659
00660 TransformInfo transformInfo( computeLinkTransforms(mountConfiguration, q) );
00661
00662 positionLinks(transformInfo);
00663
00664 if (dynamic)
00665 attachJoints(transformInfo);
00666
00667
00668
00669
00670
00671
00672 if (!dynamic) {
00673
00674
00675
00676
00677
00678 }
00679
00680
00681
00682
00683 ref<ProximityCollisionResponseHandler> proximityHandler(NewObj ProximityCollisionResponseHandler(ref<SimulatedSerialManipulator>(this),
00684 solidSystem->getCollisionDetector() ));
00685 proximityHandler->addPotentialCollisionListener( solidSystem->getCollisionResponseHandler() );
00686 solidSystem->setCollisionResponseHandler( proximityHandler );
00687
00688 }
00689
00690
00691
00692
00693
00694
00695 void SimulatedSerialManipulator::setPosition(const Point3& pos)
00696 {
00697 Transform baseTransform(manipulatorDescr->getBaseTransform());
00698 mountConfiguration = inverse(baseTransform)*linkGroups[0]->getConfiguration();
00699 mountConfiguration.setTranslationComponent(pos);
00700 linkGroups[0]->setConfiguration(mountConfiguration);
00701
00702
00703 if (!dynamic && toolGrasped) {
00704 Transform eeConfig( getEEPosition(), getEEOrientation() );
00705 proximityTool->setConfiguration( eeConfig );
00706 }
00707
00708 }
00709
00710 Point3 SimulatedSerialManipulator::getPosition() const
00711 {
00712 Transform baseTransform(manipulatorDescr->getBaseTransform());
00713 mountConfiguration = inverse(baseTransform)*linkGroups[0]->getConfiguration();
00714
00715 return mountConfiguration.getTranslation();
00716 }
00717
00718 void SimulatedSerialManipulator::setOrientation(const Orient& orient)
00719 {
00720 Transform baseTransform(manipulatorDescr->getBaseTransform());
00721 mountConfiguration = inverse(baseTransform)*linkGroups[0]->getConfiguration();
00722 mountConfiguration.setRotationComponent(orient);
00723 linkGroups[0]->setConfiguration(mountConfiguration);
00724
00725
00726 if (!dynamic && toolGrasped) {
00727 Transform eeConfig( getEEPosition(), getEEOrientation() );
00728 proximityTool->setConfiguration( eeConfig );
00729 }
00730 }
00731
00732 Orient SimulatedSerialManipulator::getOrientation() const
00733 {
00734 Transform baseTransform(manipulatorDescr->getBaseTransform());
00735 mountConfiguration = inverse(baseTransform)*linkGroups[0]->getConfiguration();
00736
00737 return mountConfiguration.getRotation();
00738 }
00739
00740 void SimulatedSerialManipulator::setConfiguration(const base::Transform& configuration)
00741 {
00742 Transform baseTransform(manipulatorDescr->getBaseTransform());
00743 mountConfiguration = configuration;
00744 linkGroups[0]->setConfiguration(mountConfiguration*baseTransform);
00745
00746
00747 if (!dynamic && toolGrasped) {
00748 Transform eeConfig( getEEPosition(), getEEOrientation() );
00749 proximityTool->setConfiguration( eeConfig );
00750 }
00751 }
00752
00753 base::Transform SimulatedSerialManipulator::getConfiguration() const
00754 {
00755 Transform baseTransform(manipulatorDescr->getBaseTransform());
00756 mountConfiguration = inverse(baseTransform)*linkGroups[0]->getConfiguration();
00757 return mountConfiguration;
00758 }
00759
00760
00761
00762
00763 base::Point3 SimulatedSerialManipulator::getEEPosition() const
00764 {
00765
00766
00767
00768 Vector3 eeToEESolidOffset( eeToEESolid.getTranslation() );
00769
00770 Vector3 eeToEESolidOffsetWorld( endSolid->getOrientation().rotate(eeToEESolidOffset) );
00771
00772
00773 return endSolid->getPosition() + eeToEESolidOffsetWorld;
00774 }
00775
00776
00777 base::Orient SimulatedSerialManipulator::getEEOrientation() const
00778 {
00779 Matrix3 eeToEESolidOrient(eeToEESolid.getRotation());
00780 return base::Orient( endSolid->getOrientation() * Orient(eeToEESolidOrient).getQuat4() );
00781 }
00782
00783
00784
00785 bool SimulatedSerialManipulator::checkProximity(ref<SimulatedTool> tool)
00786 {
00787 if (toolGrasped)
00788 return (tool == proximityTool);
00789
00790
00791
00792 Point3 eePos(getEEPosition());
00793 if ( (eePos- tool->getPosition()).length() < proximityDistance ) {
00794 Vector3 eeOrient(getEEOrientation().getVector3(Orient::EulerRPY));
00795 Vector3 toolOrient( tool->getOrientation().getVector3(Orient::EulerRPY));
00796 Vector3 eeAngDiff( Math::angleDifference(toolOrient.x,eeOrient.x),
00797 Math::angleDifference(toolOrient.y,eeOrient.y),
00798 Math::angleDifference(toolOrient.z,eeOrient.z) );
00799 if ( (Math::abs(eeAngDiff.x) < proximityAngle)
00800 && (Math::abs(eeAngDiff.y) < proximityAngle)
00801 && (Math::abs(eeAngDiff.z) < proximityAngle) ) {
00802 proximityTool = tool;
00803 return true;
00804 }
00805
00806 }
00807
00808 return false;
00809 }
00810
00811
00812
00813
00814 bool SimulatedSerialManipulator::graspTool()
00815 {
00816 if (toolGrasped) return true;
00817
00818 if (!proximityTool) return false;
00819
00820
00821 if (!checkProximity(proximityTool)) return false;
00822
00823
00824 proximityTool->setPositionOrientation( getEEPosition(), getEEOrientation() );
00825
00826
00827 proximityTool->attachTo( endSolid );
00828
00829 linkGroups[linkGroups.size()-1]->add(proximityTool);
00830
00831
00832
00833
00834 ref<CollisionCuller> cc(solidSystem->getCollisionCuller());
00835 ref<Collidable> eeCollidable( collidables[collidables.size()-1] );
00836 ref<Collidable> eeProxCollidable( proximityCollidables[proximityCollidables.size()-1] );
00837 ref<Collidable> toolLinkCollidable( proximityTool->getFirstLinkCollidable() );
00838 ref<Collidable> toolLinkProxCollidable( proximityTool->getFirstLinkProximitySensorCollidable() );
00839 Assert(eeCollidable && eeProxCollidable && toolLinkCollidable && toolLinkProxCollidable);
00840 cc->collisionEnable(false, eeCollidable, toolLinkCollidable );
00841 cc->collisionEnable(false, eeProxCollidable, toolLinkCollidable );
00842 cc->collisionEnable(false, eeCollidable, toolLinkProxCollidable );
00843 toolGrasped = true;
00844
00845 return true;
00846 }
00847
00848
00849 void SimulatedSerialManipulator::releaseGrasp()
00850 {
00851 if (!toolGrasped) return;
00852
00853 proximityTool->detatch();
00854 linkGroups[linkGroups.size()-1]->remove(proximityTool);
00855
00856
00857 Assert(solidSystem); Assert(collidables.size()>0);
00858 ref<CollisionCuller> cc(solidSystem->getCollisionCuller());
00859 ref<Collidable> eeCollidable( collidables[collidables.size()-1] );
00860 cc->collisionEnable(true, eeCollidable, proximityTool->getFirstLinkCollidable() );
00861
00862
00863 toolGrasped = false;
00864 }
00865
00866
00867
00868 ref<physics::Collidable> SimulatedSerialManipulator::createCollidable(CollidableFlags flags)
00869 {
00870 ref<CollisionCuller> cc(solidSystem->getCollisionCuller());
00871 ref<CollisionDetector> cd(solidSystem->getCollisionDetector());
00872
00873 linkProximitySurfPosition.resize(links.size());
00874
00875 collidables.resize(links.size());
00876 proximityCollidables.resize(links.size());
00877 ref<CollidableGroup> linkCollidableGroup = cc->createCollidableGroup();
00878 proximityCollidableGroup = cc->createCollidableGroup();
00879
00880 const array<Real>& linkRadii( manipulatorDescr->getLinkRadii() );
00881
00882
00883
00884 for(Int l=0; l<links.size(); l++) {
00885
00886 collidables[l] = links[l]->createCollidable(flags);
00887 linkCollidableGroup->addCollidable( collidables[l] );
00888 if (l==0) collidables[l]->setName("baseLink");
00889
00890 if (manipulatorDescr->hasLinkProximitySensors()) {
00891
00892
00893
00894
00895 ref<const Shape> linkShape( links[l]->getShape() );
00896 Real linkHeight;
00897 Real linkRadius;
00898 if (manipulatorDescr->hasGeometry()) {
00899 linkHeight = narrow_ref<const Capsule>(linkShape)->height();
00900 linkRadius = linkRadii[l];
00901 }
00902 else {
00903 linkHeight = narrow_ref<const Capsule>(linkShape)->height();
00904 linkRadius = narrow_ref<const Capsule>(linkShape)->radius();
00905 }
00906
00907 Real proxHeight = linkHeight;
00908
00909 Real proxRadius = manipulatorDescr->linkProximitySensorRange();
00910 ref<const Capsule> collisionShape(NewObj Capsule(proxHeight, proxRadius));
00911 linkProximitySurfPosition[l] = linkRadius;
00912
00913 ref<Collidable> pbody( links[l]->createCollidable(collisionShape, flags) );
00914 pbody->setInterpenetrationIsNormal(true);
00915 pbody->setUserClass(SensorCollidableClass);
00916
00917 if (l!=0)
00918 pbody->setName( pbody->getName()+" Sensor" );
00919 else
00920 pbody->setName("baseLink Sensor");
00921
00922
00923
00924
00925 pbody->setUserData(ref<SimulatedSerialManipulator>(this));
00926 proximityCollidables[l] = pbody;
00927 proximityCollidableGroup->addCollidable( proximityCollidables[l] );
00928 }
00929
00930 }
00931
00932 proximityCollidableGroup->setChildIntercollisionEnabled(false);
00933 proximityCollidableGroup->setUserClass(SensorCollidableClass);
00934
00935 disableCollisions(collidables, proximityCollidables);
00936
00937 ref<CollidableGroup> collidableGroup = cc->createCollidableGroup();
00938 collidableGroup->addCollidable( linkCollidableGroup );
00939 if (manipulatorDescr->hasLinkProximitySensors())
00940 collidableGroup->addCollidable( proximityCollidableGroup );
00941
00942 return collidableGroup;
00943 }
00944
00945
00946
00947 Real SimulatedSerialManipulator::getClosestObjectDistance(Int link) const
00948 {
00949 if (linkProximity.size()>0) {
00950 Assert(link < linkProximity.size());
00951 return linkProximity[link].dist;
00952 }
00953 else
00954 return maxDist+1.0;
00955 }
00956
00957 base::Vector3 SimulatedSerialManipulator::getClosestObjectDirection(Int link) const
00958 {
00959 if (linkProximity.size()>0) {
00960 Assert(link < linkProximity.size());
00961 return linkProximity[link].dir;
00962 }
00963 else
00964 return Vector3();
00965 }
00966
00967 Real SimulatedSerialManipulator::getClosestObjectSensorPosition(Int link) const
00968 {
00969 if (linkProximity.size()>0) {
00970 Assert(link < linkProximity.size());
00971 return linkProximity[link].intersect;
00972 }
00973 else
00974 return 0;
00975 }
00976
00977
00978
00979
00980 void SimulatedSerialManipulator::handleCollision(ref<physics::CollisionState> collisionState)
00981 {
00982 typedef SimulatedSerialManipulator::ProximityData ProximityData;
00983
00984
00985
00986 bool firstIsSensor = (collisionState->collidable1->getUserData() == ref<SimulatedSerialManipulator>(this));
00987
00988
00989 Int l=0;
00990 bool found = false;
00991 CollidableGroup::const_iterator sc( proximityCollidableGroup->begin() );
00992 CollidableGroup::const_iterator send( proximityCollidableGroup->end() );
00993 while ((sc != send) && !found) {
00994 if (*sc == (firstIsSensor?collisionState->collidable1:collisionState->collidable2) )
00995 found = true;
00996 else {
00997 ++sc; ++l;
00998 }
00999 }
01000
01001
01002 if (l < 3) return;
01003
01004 ref<const CollidableBody> body1( narrow_ref<const CollidableBody>(collisionState->collidable1) );
01005 ref<const CollidableBody> body2( narrow_ref<const CollidableBody>(collisionState->collidable2) );
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017 ref<const Solid> linkSolid( narrow_ref<const Solid>( links[l] ) );
01018 Transform T( linkSolid->getConfiguration() );
01019 Real length( linkLengths[l] );
01020 Segment3 linkSeg( T*Point3(0,0,-length/2.0), T*Point3(0,0,length/2.0) );
01021
01022
01023 ref<const Shape> obstacleShape( (firstIsSensor?body2:body1)->getShape() );
01024 Transform obstacleT( (firstIsSensor?body2:body1)->getConfiguration() );
01025
01026 Segment3 seg( obstacleShape->shortestSegmentBetween(obstacleT, linkSeg) );
01027
01028 Real dist = seg.length();
01029 Vector3 direction( seg.s - seg.e ); if (dist > 0) direction.normalize();
01030 Real intersect = (seg.e - linkSeg.s).length();
01031 ProximityData proxData(dist, intersect, direction);
01032 linkProximity[l] = proxData;
01033
01034
01035 if (!firstIsSensor) base::swap(body1, body2);
01036
01037
01038
01039
01040
01041
01042 Transform c;
01043 c.setToTranslation( seg.s + 0.5*(seg.e-seg.s) );
01044 Matrix3 R; R.setIdentity();
01045 if (!seg.e.equals(seg.s)) {
01046 Vector3 z( seg.e - seg.s ); z.normalize();
01047 Vector3 x(1,0,0);
01048 if (x.equals(z) || x.equals(-z)) x = Vector3(0,1,0);
01049 if (x.equals(z) || x.equals(-z)) x = Vector3(0,0,1);
01050 if (x.equals(z) || x.equals(-z)) x = Vector3(1,1,0);
01051 Vector3 y( cross(x,z) ); y.normalize();
01052 x = cross( y,z ); x.normalize();
01053 R.setColumn(1,x);
01054 R.setColumn(2,y);
01055 R.setColumn(3,z);
01056 }
01057 c.setRotationComponent( R );
01058 VisualDebugUtil::addDebugCylinderObject(dist, 0.005, body1->getName()+"proxseg", c, gfx::Color4("yellow"));
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086 }
01087