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/SimulatedTool>
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/Cylinder>
00040 #include <physics/Solid>
00041 #include <physics/ConstraintGroup>
00042 #include <physics/FixedConstraint>
00043 #include <physics/Joint>
00044 #include <physics/HingeJoint>
00045 #include <physics/SliderJoint>
00046 #include <physics/Motor>
00047 #include <physics/CollisionCuller>
00048 #include <physics/CollisionDetector>
00049 #include <physics/CollisionState>
00050 #include <physics/NullCollisionResponseHandler>
00051
00052 #include <physics/VisualDebugUtil>
00053
00054 #include <robot/KinematicChain>
00055
00056
00057 using robot::sim::SimulatedTool;
00058
00059 using base::Point3;
00060 using base::Orient;
00061 using base::Externalizer;
00062 using base::Dimension3;
00063 using base::Transform;
00064 using gfx::Line3;
00065 using gfx::Segment3;
00066 using gfx::Color4;
00067 using physics::BoundingBox;
00068 using physics::Collidable;
00069 using physics::CollidableBody;
00070 using physics::CollidableGroup;
00071 using physics::CollisionState;
00072 using physics::CollisionCuller;
00073 using physics::CollisionDetector;
00074 using physics::CollisionResponseHandler;
00075 using physics::NullCollisionResponseHandler;
00076 using physics::Shape;
00077 using physics::Box;
00078 using physics::Sphere;
00079 using physics::Cylinder;
00080 using physics::Material;
00081 using physics::Solid;
00082 using physics::SpatialGroup;
00083 using physics::SpatialTransform;
00084 using physics::ConstraintGroup;
00085 using physics::FixedConstraint;
00086 using physics::Joint;
00087 using physics::HingeJoint;
00088 using physics::SliderJoint;
00089 using physics::Motor;
00090
00091 using physics::VisualDebugUtil;
00092
00093 using robot::KinematicChain;
00094 using robot::sim::SimulatedKinematicChain;
00095 using robot::sim::SimulatedTool;
00096
00097
00098 #include <physics/ODESolidConnectedCollidableBody>
00099 using physics::SolidConnectedCollidableBody;
00100 using physics::ODESolidConnectedCollidableBody;
00101
00102
00103 #include <ode/ode.h>
00104 #include <ode/rotation.h>
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 SimulatedTool::SimulatedTool(ref<const robot::ToolDescription> toolDescription,
00139 const base::Point3& initialPosition, const base::Orient& initialOrientation,
00140 ref<physics::SolidSystem> solidSystem, bool dynamic)
00141 : SimulatedKinematicChain(solidSystem, dynamic), toolDescr(toolDescription), attached(false)
00142 {
00143 Assert(solidSystem!=0);
00144
00145 chain = toolDescr->getKinematicChain();
00146 q.resize(chain.dof());
00147 spatialGroup = ref<SpatialGroup>(NewObj SpatialGroup());
00148
00149 construct(initialPosition, initialOrientation);
00150 }
00151
00152
00153
00154
00155 bool SimulatedTool::formatSupported(String format, Real version, ExternalizationType type) const
00156 {
00157 return false;
00158 }
00159
00160 void SimulatedTool::externalize(base::Externalizer& e, String format, Real version)
00161 {
00162 if (format == "") format = "xml";
00163
00164 if (!formatSupported(format,version,e.ioType()))
00165 throw std::invalid_argument(Exception(String("format ")+format+" v"+base::realToString(version)+" unsupported"));
00166
00167 }
00168
00169
00170
00171 void SimulatedTool::setJointForce(Int j, Real f)
00172 {
00173 Assertm((j>=1)&&(j<=chain.dof()), "joint index in range");
00174
00175 if (!dynamic) return;
00176
00177 Int l = chain.linkIndexOfVariable(j-1);
00178
00179 ref<Motor> motor(joints[l]->getMotor(1));
00180 motor->setTargetVel( (f>0)?10:-10 );
00181 motor->setMaxForce(f);
00182 }
00183
00184 void SimulatedTool::setJointVel(Int j, Real v, Real maxForce)
00185 {
00186 Assertm((j>=1)&&(j<=chain.dof()), "joint index in range");
00187
00188 if (!dynamic) return;
00189
00190 Int l = chain.linkIndexOfVariable(j-1);
00191
00192 ref<Motor> motor(joints[l]->getMotor(1));
00193 motor->setTargetVel(v);
00194 motor->setMaxForce(maxForce);
00195 }
00196
00197
00198 void SimulatedTool::setJointPos(Int j, Real p)
00199 {
00200 Assertm((j>=1)&&(j<=chain.dof()), "joint index in range");
00201
00202 q[j-1] = p;
00203
00204
00205
00206
00207 Transform mountConfiguration = mountSpatial->getConfiguration();
00208
00209 TransformInfo transformInfo( computeLinkTransforms(mountConfiguration, q) );
00210 positionLinks(transformInfo);
00211
00212
00213 }
00214
00215
00216 Real SimulatedTool::getJointPos(Int j) const
00217 {
00218 Assertm((j>=1)&&(j<=chain.dof()), "joint index in range");
00219
00220 if (dynamic) {
00221
00222
00223
00224
00225 Int l = chain.linkIndexOfVariable(j-1);
00226
00227 if (chain[l].type() == KinematicChain::Link::Revolute) {
00228
00229 ref<HingeJoint> hinge(narrow_ref<HingeJoint>(joints[l]));
00230
00231 q[j-1] = hinge->getAngle();
00232
00233 } else {
00234 ref<SliderJoint> slider(narrow_ref<SliderJoint>(joints[l]));
00235 q[j-1] = slider->getPosition();
00236 }
00237
00238 } else {
00239
00240
00241
00242
00243
00244
00245 }
00246
00247 return q[j-1];
00248
00249 }
00250
00251
00252 Real SimulatedTool::getJointVel(Int j) const
00253 {
00254 Assertm((j>=1)&&(j<=chain.dof()), "joint index in range");
00255
00256 if (!dynamic) return 0;
00257
00258 Int l = chain.linkIndexOfVariable(j-1);
00259
00260 if (chain[l].type() == KinematicChain::Link::Revolute) {
00261
00262 ref<HingeJoint> hinge(narrow_ref<HingeJoint>(joints[l]));
00263 return hinge->getAngleRate();
00264 }
00265 else {
00266
00267 ref<SliderJoint> slider(narrow_ref<SliderJoint>(joints[l]));
00268 return slider->getPositionRate();
00269 }
00270
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 SimulatedTool::TransformInfo SimulatedTool::computeLinkTransforms(const Transform& mountTransform, const base::Vector& q) const
00283 {
00284 TransformInfo transformInfo;
00285 transformInfo.mountTransform = mountTransform;
00286 transformInfo.q.reset(q);
00287
00288 array<Transform>& A(transformInfo.A);
00289 array<Transform>& T(transformInfo.T);
00290 array<Transform>& SLT(transformInfo.SLT);
00291 A.resize(chain.size()+1);
00292 T.resize(A.size());
00293 SLT.resize(A.size());
00294
00295 A[0] = transformInfo.mountTransform;
00296 T[0] = A[0];
00297 Int j=0;
00298
00299
00300 transformInfo.mountToBaseSolid = Transform(Vector3(linkLengths[1],0,0));
00301
00302 for (Int l=1; l<=chain.size(); l++) {
00303
00304 const KinematicChain::Link& link(chain[l-1]);
00305
00306
00307
00308 Vector lq(link.dof());
00309 if (lq.size()>0)
00310 lq[0] = transformInfo.q[j];
00311 A[l] = base::toMatrix4(link.kinematicTransform(lq));
00312
00313
00314
00315 T[l] = T[l-1]*A[l];
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 SLT[l] = Quat4(Vector3(0,1,0),consts::Pi/2.0) * Transform(Vector3(0,0,-linkLengths[l]/2.0));
00326
00327 if (link.isDHType()) {
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 Real incline = (!Math::equals(link.getD(),0))? Math::asin(link.getD()/linkLengths[l]) : 0;
00338 if (!Math::equals(incline,0)) {
00339 Transform rotYl = Quat4(Vector3(0,1,0),-incline);
00340 Transform rotXl = Quat4(Vector3(1,0,0), link.getAlpha());
00341 Transform rotXlInv = Quat4(Vector3(1,0,0),-link.getAlpha());
00342 Transform rotYlm1 = rotXlInv * rotYl * rotXl;
00343
00344 SLT[l] = rotYlm1 * SLT[l];
00345 }
00346
00347
00348 }
00349
00350 if (l==chain.size())
00351 transformInfo.eeToEESolid = inverse(SLT[l]);
00352
00353 j += link.dof();
00354 }
00355
00356
00357 return transformInfo;
00358 }
00359
00360
00361
00362
00363
00364 void SimulatedTool::createLinks(const array<base::Dimension3>& linkDims)
00365 {
00366
00367
00368
00369
00370 Assert(chain.size() > 0);
00371
00372 links.resize(chain.size()+1);
00373 linkGroups.resize(chain.size()+1);
00374
00375
00376 for (Int l=1; l<=chain.size(); l++) {
00377 const Dimension3& dim(linkDims[l]);
00378 ref<Box> box(NewObj Box(dim.x,dim.y,dim.z));
00379 ref<Material> material(NewObj physics::Material());
00380
00381
00382 switch (l%10) {
00383 case 0: material->setBaseColor(gfx::Color3(0.6,0.6,0.6)); break;
00384 case 1: material->setBaseColor(gfx::Color3(0,1,0)); break;
00385 case 2: material->setBaseColor(gfx::Color3(0+0.1,1-0.1,0+0.1)); break;
00386 case 3: material->setBaseColor(gfx::Color3(0+0.2,1-0.2,0+0.2)); break;
00387 case 4: material->setBaseColor(gfx::Color3(0+0.3,1-0.3,0+0.3)); break;
00388 case 5: material->setBaseColor(gfx::Color3(0+0.4,1-0.4,0+0.4)); break;
00389 case 6: material->setBaseColor(gfx::Color3(0+0.5,1-0.5,0+0.5)); break;
00390 case 7: material->setBaseColor(gfx::Color3(0+0.6,1-0.6,0+0.6)); break;
00391 case 8: material->setBaseColor(gfx::Color3(1,1,1)); break;
00392 case 9: material->setBaseColor(gfx::Color3(1,0,0)); break;
00393 default:
00394 material->setBaseColor(gfx::Color3(0,0,1));
00395 }
00396
00397
00398 links[l] = solidSystem->createSolid(box,material);
00399 links[l]->setName(getToolDescription()->getName()+" "
00400 +String("link ")+base::intToString(l));
00401 solidSystem->addSolid(links[l]);
00402
00403
00404
00405
00406 ref<SpatialTransform> linkTransform( NewObj SpatialTransform() );
00407 linkTransform->setChild( links[l] );
00408 ref<SpatialGroup> linkGroup( NewObj SpatialGroup() );
00409 linkGroup->add(linkTransform);
00410 linkGroup->setImplicitConfiguration(linkTransform);
00411 if (l > 1) linkGroups[l-1]->add(linkGroup);
00412 linkGroups[l] = linkGroup;
00413
00414 if (l == 1)
00415 firstSolid = links[l];
00416 else
00417 if (l == chain.size())
00418 endSolid = links[l];
00419 }
00420
00421
00422
00423
00424 mountSpatial = ref<SpatialTransform>( NewObj SpatialTransform() );
00425 mountSpatial->setChild( linkGroups[1] );
00426
00427 }
00428
00429
00430
00431 void SimulatedTool::positionLinks(const SimulatedTool::TransformInfo& transformInfo)
00432 {
00433 Assert(links.size() == chain.size()+1);
00434
00435
00436 firstLinkSolidToMount = transformInfo.mountToBaseSolid;
00437 mountSpatial->setTransform(firstLinkSolidToMount);
00438
00439
00440 const array<Transform>& SLT( transformInfo.SLT );
00441 const array<Transform>& T( transformInfo.T );
00442
00443 for (Int l=1; l<=chain.size(); l++) {
00444
00445 ref<SpatialGroup> linkGroup(linkGroups[l]);
00446 SpatialGroup::iterator firstChild = linkGroup->begin();
00447
00448
00449
00450 ref<SpatialTransform> linkSpatialTransform( narrow_ref<SpatialTransform>( *firstChild ) );
00451 linkSpatialTransform->setTransform( SLT[l] );
00452
00453
00454 linkSpatialTransform->setConfiguration( T[l] );
00455
00456 }
00457
00458 }
00459
00460
00461
00462 void SimulatedTool::disableCollisions(const array<ref<physics::Collidable> >& collidables,
00463 const array<ref<physics::Collidable> >& proximityCollidables)
00464 {
00465 Assert(solidSystem);
00466 Assert(links.size() == chain.size()+1);
00467
00468 ref<CollisionCuller> cc(solidSystem->getCollisionCuller());
00469
00470 bool disableNextWithPrev = false;
00471
00472
00473 for (Int l=2; l<=chain.size(); l++) {
00474
00475 cc->collisionEnable(false,collidables[l-1],collidables[l]);
00476
00477
00478 cc->collisionEnable(false,collidables[l], proximityCollidables[l]);
00479
00480 cc->collisionEnable(false,collidables[l-1],proximityCollidables[l]);
00481 cc->collisionEnable(false,proximityCollidables[l-1],collidables[l]);
00482
00483
00484 if (disableNextWithPrev) {
00485 cc->collisionEnable(false,collidables[l-2],collidables[l]);
00486 cc->collisionEnable(false,collidables[l-2],proximityCollidables[l]);
00487 disableNextWithPrev = false;
00488 }
00489
00490 if (linkLengths[l]<=0.05)
00491 disableNextWithPrev = true;
00492
00493 }
00494
00495
00496 }
00497
00498
00499 void SimulatedTool::attachJoints(const SimulatedTool::TransformInfo& transformInfo)
00500 {
00501 if (links.size() < 2) return;
00502
00503
00504 const array<Transform>& T( transformInfo.T );
00505 const array<Transform>& SLT( transformInfo.SLT );
00506
00507 ref<ConstraintGroup> cgroup = solidSystem->createConstraintGroup();
00508 solidSystem->addConstraintGroup(cgroup);
00509 ref<Motor> motor;
00510 joints.resize(links.size()-1);
00511
00512 for (Int l=2; l<links.size(); l++) {
00513
00514
00515 const KinematicChain::Link& link(chain[l-1]);
00516 ref<Joint> joint;
00517
00518 if (link.isDHType()) {
00519
00520
00521
00522
00523
00524 Vector3 axis( Vector3(1,0,0) );
00525 if (l>1) {
00526 axis = (T[l-1]*SLT[l-1]).rotate(axis);
00527 axis = inverse(T[l]*SLT[l]).rotate(axis);
00528 } else {
00529 axis = T[0].rotate(Vector3(0,0,1));
00530 axis = inverse(T[1]*SLT[1]).rotate(axis);
00531 }
00532
00533
00534 if (link.type() == KinematicChain::Link::Revolute) {
00535
00536 ref<HingeJoint> hinge = solidSystem->createHingeJoint();
00537 joint = hinge;
00538 cgroup->addConstraint(hinge);
00539 joints[l-1] = joint;
00540 Assert(links[l-1]);
00541 joint->attach(links[l], links[l-1]);
00542
00543
00544 hinge->setAnchor( Point3(0,0,-linkLengths[l]/2) );
00545 hinge->setAxis( axis );
00546
00547
00548 if (! ((link.minLimit() <= -consts::Pi)&&(link.maxLimit() >= consts::Pi)) ) {
00549 hinge->setLowStop(link.minLimit() - Math::degToRad(1) );
00550 hinge->setHighStop(link.maxLimit() + Math::degToRad(1) );
00551 hinge->setStopRestitution(0.2);
00552 }
00553
00554
00555 motor = solidSystem->createMotor();
00556 hinge->attachMotor(1, motor);
00557
00558 }
00559 else if (link.type() == KinematicChain::Link::Prismatic) {
00560
00561 ref<SliderJoint> slider = solidSystem->createSliderJoint();
00562 joint = slider;
00563 cgroup->addConstraint(slider);
00564 joints[l-1] = joint;
00565 Assert(links[l-1]);
00566 joint->attach(links[l], links[l-1]);
00567
00568 slider->setAxis( axis );
00569
00570
00571 slider->setLowStop(link.minLimit());
00572 slider->setHighStop(link.maxLimit());
00573 slider->setStopRestitution(0.2);
00574
00575
00576 motor = solidSystem->createMotor();
00577 slider->attachMotor(1, motor);
00578
00579 Logln("Warning: Prismatic joints not fully implemented");
00580 }
00581 }
00582 else
00583 throw std::invalid_argument(Exception("unknown/unsupported joint type: " + link.type()));
00584
00585 motor->setTargetVel(0);
00586 motor->setMaxForce(0.001);
00587
00588 }
00589
00590 }
00591
00592
00593
00594 void SimulatedTool::construct(const base::Point3& initialPosition,
00595 const base::Orient& initialOrientation)
00596 {
00597 Transform mountConfiguration = Transform(initialPosition, initialOrientation);
00598
00599 linkGroups.clear();
00600 createLinks(computeLinkDimensions(array<Real>(0)));
00601
00602
00603
00604
00605 Assert(chain.size() > 0);
00606 Vector q(chain.dof());
00607
00608
00609 for(Int j=0; j<chain.dof(); j++) {
00610 const KinematicChain::Link& link(chain.linkOfVariable(j));
00611 q[j] = link.variable();
00612 }
00613
00614
00615 TransformInfo transformInfo( computeLinkTransforms(mountConfiguration, q) );
00616
00617 positionLinks(transformInfo);
00618
00619 if (dynamic)
00620 attachJoints(transformInfo);
00621
00622 if (!dynamic) {
00623
00624
00625
00626 ref<CollisionResponseHandler> nullHandler(NewObj NullCollisionResponseHandler(solidSystem->getCollisionDetector()));
00627 solidSystem->setCollisionResponseHandler( nullHandler );
00628 }
00629
00630
00631
00632
00633 ref<ProximityCollisionResponseHandler> proximityHandler(NewObj ProximityCollisionResponseHandler(ref<SimulatedTool>(this),
00634 solidSystem->getCollisionDetector() ));
00635 proximityHandler->addPotentialCollisionListener( solidSystem->getCollisionResponseHandler() );
00636 solidSystem->setCollisionResponseHandler( proximityHandler );
00637
00638 }
00639
00640
00641
00642
00643
00644
00645 void SimulatedTool::setPosition(const Point3& pos)
00646 {
00647 Transform mountConfiguration = mountSpatial->getConfiguration();
00648 mountConfiguration.setTranslationComponent(pos);
00649 mountSpatial->setConfiguration(mountConfiguration);
00650 }
00651
00652 Point3 SimulatedTool::getPosition() const
00653 {
00654 Transform mountConfiguration = mountSpatial->getConfiguration();
00655 return mountConfiguration.getTranslation();
00656 }
00657
00658 void SimulatedTool::setOrientation(const Orient& orient)
00659 {
00660 Transform mountConfiguration = mountSpatial->getConfiguration();
00661 mountConfiguration.setRotationComponent(orient);
00662 mountSpatial->setConfiguration(mountConfiguration);
00663 }
00664
00665 Orient SimulatedTool::getOrientation() const
00666 {
00667 Transform mountConfiguration = mountSpatial->getConfiguration();
00668 return mountConfiguration.getRotation();
00669 }
00670
00671 void SimulatedTool::setConfiguration(const base::Transform& configuration)
00672 {
00673 Transform mountConfiguration = configuration;
00674 mountSpatial->setConfiguration(mountConfiguration);
00675 }
00676
00677 base::Transform SimulatedTool::getConfiguration() const
00678 {
00679 Transform mountConfiguration = mountSpatial->getConfiguration();
00680 return mountConfiguration;
00681 }
00682
00683
00684
00685
00686
00687 void SimulatedTool::attachTo(ref<physics::Solid> manipEESolid)
00688 {
00689 KinematicChain::Link link( chain[0] );
00690
00691 Assert(firstSolid);
00692 Assert(manipEESolid);
00693
00694 if (dynamic) {
00695
00696
00697 mountConstraintGroup = solidSystem->createConstraintGroup();
00698 Assert(!link.isActive());
00699 ref<FixedConstraint> fixed = solidSystem->createFixedConstraint();
00700 mountConstraintGroup->addConstraint(fixed);
00701 links[0] = manipEESolid;
00702 fixed->attach(manipEESolid, firstSolid);
00703
00704 }
00705
00706 attached = true;
00707 }
00708
00709
00710
00711 void SimulatedTool::detatch()
00712 {
00713 if (attached) {
00714 const KinematicChain::Link& link(chain[0]);
00715
00716 if (dynamic) {
00717
00718 Assert(!link.isActive());
00719
00720 mountConstraintGroup->clear();
00721 mountConstraintGroup = ref<ConstraintGroup>(0);
00722
00723 }
00724
00725 attached=false;
00726 }
00727
00728 }
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759 ref<physics::Collidable> SimulatedTool::createCollidable(CollidableFlags flags)
00760 {
00761 Assert(solidSystem);
00762 ref<CollisionCuller> cc(solidSystem->getCollisionCuller());
00763 ref<CollisionDetector> cd(solidSystem->getCollisionDetector());
00764 Assert(cc); Assert(cd);
00765
00766 const Real proximityEnvelope = 5.0;
00767 linkProximitySurfPosition.resize(links.size());
00768
00769 collidables.resize(links.size());
00770 proximityCollidables.resize(links.size());
00771 ref<CollidableGroup> linkCollidableGroup = cc->createCollidableGroup();
00772 proximityCollidableGroup = cc->createCollidableGroup();
00773
00774
00775
00776 for(Int l=1; l<=chain.size(); l++) {
00777
00778 Assert(links[l]);
00779 collidables[l] = links[l]->createCollidable(flags);
00780 linkCollidableGroup->addCollidable( collidables[l] );
00781 if (l==1) collidables[l]->setName("firstLink");
00782
00783
00784 ref<const Shape> linkShape( links[l]->getShape() );
00785 Dimension3 e = narrow_ref<const Box>(linkShape)->dimensions()/2.0;
00786 Real radius = ( Math::sqrt(e.x*e.x + e.y*e.y) )*proximityEnvelope;
00787 Real height = e.z*2.0;
00788 ref<const Cylinder> collisionShape(NewObj Cylinder(height, radius));
00789 linkProximitySurfPosition[l] = radius;
00790
00791 ref<Collidable> pbody( links[l]->createCollidable(collisionShape, flags) );
00792 pbody->setInterpenetrationIsNormal(true);
00793 pbody->setUserClass(SensorCollidableClass);
00794
00795 if (l!=1)
00796 pbody->setName( pbody->getName()+" Sensor" );
00797 else
00798 pbody->setName("firstLink Sensor");
00799 VisualDebugUtil::addDebugObject(collisionShape, pbody->getName(), links[l]->getConfiguration(),Color4("lime green",0.2));
00800 VisualDebugUtil::addDebugObject(linkShape, links[l]->getName(), links[l]->getConfiguration(),Color4("yellow",0.2));
00801
00802
00803 pbody->setUserData(ref<SimulatedTool>(this));
00804 proximityCollidables[l] = pbody;
00805 proximityCollidableGroup->addCollidable( proximityCollidables[l] );
00806
00807 }
00808
00809 proximityCollidableGroup->setChildIntercollisionEnabled(false);
00810 proximityCollidableGroup->setUserClass(SensorCollidableClass);
00811
00812 disableCollisions(collidables, proximityCollidables);
00813
00814 ref<CollidableGroup> collidableGroup = cc->createCollidableGroup();
00815 collidableGroup->addCollidable( linkCollidableGroup );
00816 collidableGroup->addCollidable( proximityCollidableGroup );
00817
00818 return collidableGroup;
00819 }
00820
00821
00822
00823 Real SimulatedTool::getClosestObjectDistance(Int link) const
00824 {
00825
00826 if (linkProximity.size()>0) {
00827 Assert(link < linkProximity.size());
00828 return linkProximity[link].dist;
00829 }
00830 else
00831 return maxDist+1.0;
00832 }
00833
00834 base::Vector3 SimulatedTool::getClosestObjectDirection(Int link) const
00835 {
00836 if (linkProximity.size()>0) {
00837 Assert(link < linkProximity.size());
00838 return linkProximity[link].dir;
00839 }
00840 else
00841 return Vector3();
00842 }
00843
00844 Real SimulatedTool::getClosestObjectSensorPosition(Int link) const
00845 {
00846 if (linkProximity.size()>0) {
00847 Assert(link < linkProximity.size());
00848 return linkProximity[link].intersect;
00849 }
00850 else
00851 return 0;
00852 }
00853
00854
00855
00856
00857 void SimulatedTool::handleCollision(ref<physics::CollisionState> collisionState)
00858 {
00859 typedef SimulatedTool::ProximityData ProximityData;
00860
00861
00862
00863 bool firstIsSensor = (collisionState->collidable1->getUserData() == ref<SimulatedTool>(this));
00864
00865
00866 Int l=1;
00867 bool found = false;
00868 CollidableGroup::const_iterator sc( proximityCollidableGroup->begin() );
00869 CollidableGroup::const_iterator send( proximityCollidableGroup->end() );
00870 while ((sc != send) && !found) {
00871 if (*sc == (firstIsSensor?collisionState->collidable1:collisionState->collidable2) )
00872 found = true;
00873 else {
00874 ++sc; ++l;
00875 }
00876 }
00877
00878 ref<const CollidableBody> body1( narrow_ref<const CollidableBody>(collisionState->collidable1) );
00879 ref<const CollidableBody> body2( narrow_ref<const CollidableBody>(collisionState->collidable2) );
00880
00881
00882
00883
00884
00885 ref<const Solid> linkSolid( narrow_ref<const Solid>( links[l] ) );
00886 Transform T( linkSolid->getConfiguration() );
00887 Real length( linkLengths[l] );
00888 Segment3 linkSeg( T*Point3(0,0,-length/2.0), T*Point3(0,0,length/2.0) );
00889
00890
00891 ref<const Shape> obstacleShape( (firstIsSensor?body2:body1)->getShape() );
00892 Transform obstacleT( (firstIsSensor?body2:body1)->getConfiguration() );
00893
00894 Segment3 seg( obstacleShape->shortestSegmentBetween(obstacleT, linkSeg) );
00895
00896 Real dist = seg.length();
00897 Vector3 direction( seg.e - seg.s ); if (dist > 0) direction.normalize();
00898 Real intersect = (seg.e - linkSeg.s).length();
00899 ProximityData proxData(dist, intersect, direction);
00900 linkProximity[l] = proxData;
00901
00902
00903 if (!firstIsSensor) base::swap(body1, body2);
00904
00905
00906 VisualDebugUtil::setColor(body1->getName(), Color4("red",0.4));
00907
00908 }
00909