Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

robot/sim/SimulatedTool.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)2002 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018   $Id: SimulatedTool.cpp 1033 2004-02-11 20:47:52Z jungd $
00019   $Revision: 1.12 $
00020   $Date: 2004-02-11 15:47:52 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
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 SimulatedTool::SimulatedTool(ref<base::VFile> toolSpecification,
00109                              const base::Point3& initialPosition, const base::Orient& initialOrientation,
00110                              ref<physics::SolidSystem> solidSystem, bool dynamic)
00111   : SimulatedKinematicChain(solidSystem, dynamic), attached(false)
00112 {
00113   Assert(solidSystem!=0);
00114 
00115   chain = toolDescr.getKinematicChain();
00116   q.reset(zeroVector(chain.dof()));
00117   spatialGroup = ref<SpatialGroup>(NewObj SpatialGroup()); // a group to put all the Solids in
00118 
00119   // read in supported formats
00120   if (toolSpecification->extension() == "xml") {
00121 
00122     // read in parameters 
00123     try {
00124       Externalizer e(Externalizable::Input, toolSpecification);
00125       externalize(e,"xml",1.0);
00126     } catch (std::exception&) {
00127       throw std::invalid_argument(Exception("not a valid tool .xml file."));
00128     }
00129 
00130   }
00131   else
00132     throw std::invalid_argument(Exception("file format unsupported."));
00133 
00134   construct(initialPosition, initialOrientation);
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()); // a group to put all the Solids in
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   //... actually move the links
00205   //hack!!! (expensive - only need to update the joint in question)
00206 
00207   Transform mountConfiguration = mountSpatial->getConfiguration();
00208   
00209   TransformInfo transformInfo( computeLinkTransforms(mountConfiguration, q) );
00210   positionLinks(transformInfo);
00211     
00212   //hack!!!
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) { // get joint pos from physics::Joint
00221     
00222     // NB: physics::Joints have their 0 pos at the position/orientation
00223     //  at which the two bodies were initially attached.  That was
00224     //  computed from the tool joint parameter home position.
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 { // prismatic
00234       ref<SliderJoint> slider(narrow_ref<SliderJoint>(joints[l]));
00235       q[j-1] = slider->getPosition();
00236     }
00237     
00238   } else { // static
00239     /*// !!!fix indices for tool (copied from manip)
00240     Transform relConfig = inverse( links[j]->getConfiguration() )*links[j-1]->getConfiguration();
00241     Real rotAboutZ = Math::normalizeAngle(relConfig.getRotation().getVector(Orient::EulerZYX)[0]);
00242     Debugln(Tmp,"rotAboutZ=" << rotAboutZ);
00243     return rotAboutZ;
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 { // prismatic
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); // convenient aliases
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; // link 0
00296   T[0] = A[0];
00297   Int j=0; // joint variable index
00298 
00299   // transform from mount point to first link - translate origin to (other) link end
00300   transformInfo.mountToBaseSolid = Transform(Vector3(linkLengths[1],0,0));
00301   
00302   for (Int l=1; l<=chain.size(); l++) { // for each link
00303     
00304     const KinematicChain::Link& link(chain[l-1]);
00305     
00306     //
00307     // ask KinematicChain to compute the transform for each link
00308     Vector lq(link.dof());
00309     if (lq.size()>0) // this currently only handles 0 or 1-dof links (!!!)
00310       lq[0] = transformInfo.q[j]; 
00311     A[l] = base::toMatrix4(link.kinematicTransform(lq));
00312     
00313     //
00314     // accumulate inter-link transforms 
00315     T[l] = T[l-1]*A[l]; 
00316     
00317     //
00318     // finally compute the relative configuration of each link's Solid from its origin
00319 
00320     // Rotate the z-axis into the x-axis, as the link coord. frame has the x-axis along
00321     //  the link length, but the Solid's z-axis is the long one.
00322     // Also translate back 1/2 the Solid length along the long axis (z)
00323     //  (as the origin of the Solid is at its center of mass, but the origin of a link
00324     //   is at its end)
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 //!!! fix comment
00329       // We also want to rotate the Solid so that the ends meet even if there
00330       //  is a displacement due to DH-parameter d
00331       //  (this will be a rotation about the y-axis of link l-1 to make the Solid's z-axis
00332       //   point to the previous link's origin rather than being parallel with
00333       //   the link x-axis.  To achieve this we bring link Solid l's y&z-axes parallel to
00334       //   those of link l-1 by reversing the skew DH-parameter alpha, then rotate about the x-axis,
00335       //   and then redo the skew)
00336 //!!!check use of link.d is OK here (need to use q[0] if Prismatic??)
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]); //!!! check
00352     
00353     j += link.dof();
00354   } // for each link
00355 
00356   
00357   return transformInfo;
00358 }
00359 
00360 
00361 
00362 
00363 
00364 void SimulatedTool::createLinks(const array<base::Dimension3>& linkDims)
00365 {
00366   // We create a Solid for each link and place it in SolidSystem
00367   // Unless the geometry is specified, the Shape will be a Box who's dimensions
00368   // are specified in linkDims[]
00369   // The links are also chained together using SpatialGroups
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++) { // for each link
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     // colour
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     // add it to the system
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     // create a SpatialGroup which will hold a SpatialTransform warpping this link's Solid
00404     //  (as the link Solid may be transformed from the link origin), and the next link's
00405     //  group.
00406     ref<SpatialTransform> linkTransform( NewObj SpatialTransform() );
00407     linkTransform->setChild( links[l] ); // wrap link in a SpatialTransform
00408     ref<SpatialGroup> linkGroup( NewObj SpatialGroup() );
00409     linkGroup->add(linkTransform); // add it to the link group
00410     linkGroup->setImplicitConfiguration(linkTransform); // the configuration of the link group is synonymous with the linkTransform
00411     if (l > 1) linkGroups[l-1]->add(linkGroup); // add the linkGroup to the previous link's linkGroup
00412     linkGroups[l] = linkGroup; // stash it into the link group array
00413     
00414     if (l == 1)
00415       firstSolid = links[l];
00416     else
00417       if (l == chain.size())
00418         endSolid = links[l];
00419   }
00420   
00421 
00422   // the mount point is a SpatialTransform that wraps the first link such that the mount is at the
00423   //  appropriate point (opposite end to the end-effector)  
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); // links must already have been created
00434 
00435   // set mount transform
00436   firstLinkSolidToMount = transformInfo.mountToBaseSolid;
00437   mountSpatial->setTransform(firstLinkSolidToMount);
00438   
00439   // some convenient aliases
00440   const array<Transform>& SLT( transformInfo.SLT );   // transforms from the link's Solid coord. frame to the link frame
00441   const array<Transform>& T( transformInfo.T );
00442 
00443   for (Int l=1; l<=chain.size(); l++) { // for each link
00444 
00445     ref<SpatialGroup> linkGroup(linkGroups[l]);
00446     SpatialGroup::iterator firstChild = linkGroup->begin();
00447 
00448     // set the transform from link origin to Solid origin first,
00449     // so that the Solid is properly configured when SpatialTransform configuration is set
00450     ref<SpatialTransform> linkSpatialTransform( narrow_ref<SpatialTransform>( *firstChild ) );
00451     linkSpatialTransform->setTransform( SLT[l] );
00452     
00453     // set SpatialTransform configuration (hence configuring its Solid child, and implicitly the linkGroup)
00454     linkSpatialTransform->setConfiguration( T[l] ); 
00455     
00456   } // for each link
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); // links must already have been created
00467   
00468   ref<CollisionCuller> cc(solidSystem->getCollisionCuller());
00469   
00470   bool disableNextWithPrev = false;   // if true, disabled collisions between link's l & l-2 (in addition to the
00471                                       // usual disable between l & l-1.  This occurs when link l-1 has a length of 0 (coincident origins)
00472   
00473   for (Int l=2; l<=chain.size(); l++) { // for each link
00474     // disable collision detection between consecutive links
00475     cc->collisionEnable(false,collidables[l-1],collidables[l]);
00476     
00477     // and between link Solid Collidables & their corresponding proximity sensor Collidable
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; // don't collide link l+1 with l-1 as they will be close on account of this link l being 0 length
00492     
00493   }  
00494   
00495 
00496 }
00497 
00498 
00499 void SimulatedTool::attachJoints(const SimulatedTool::TransformInfo& transformInfo)
00500 {
00501   if (links.size() < 2) return; // no joints
00502 
00503   // alias
00504   const array<Transform>& T( transformInfo.T );     // accumulated transformations for each link (transforms from frame l to base frame)
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); // should this be link.size()???!!!
00511   
00512   for (Int l=2; l<links.size(); l++) { // for each link (except the first)
00513     // connect it to the previous link in the chain
00514   
00515     const KinematicChain::Link& link(chain[l-1]);
00516     ref<Joint> joint;
00517     
00518     if (link.isDHType()) {    // Connect using a HingeJoint for revolute joints and a SliderJoint for prismatic joints
00519       
00520       // All DH type joints have an axis of Z - which is the Solid's X-axis
00521       //  The axis is the z-axis of the previous link (l-1)
00522       // (they are specified relative to link l - hence we must transform z-axis
00523       //  of link l-1 into link l's coord. frame.)  
00524       Vector3 axis( Vector3(1,0,0) ); // untransformed Solid x-axis (link z-axis)
00525       if (l>1) {
00526         axis = (T[l-1]*SLT[l-1]).rotate(axis);  // x-axis of link Solid l-1 
00527         axis = inverse(T[l]*SLT[l]).rotate(axis);  // x-axis of link Solid l-1 in frame of link Solid l
00528       } else { // connection to base is special case
00529         axis = T[0].rotate(Vector3(0,0,1)); // z-axis in base frame
00530         axis = inverse(T[1]*SLT[1]).rotate(axis);  // z-axis of base frame in frame of link Solid l
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         // the anchor is at the end of the link (toward the base - not the origin end)
00544         hinge->setAnchor( Point3(0,0,-linkLengths[l]/2) );
00545         hinge->setAxis( axis ); 
00546   
00547         // set limits
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         // now attach a Motor to drive the joint
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         // set limits
00571         slider->setLowStop(link.minLimit());
00572         slider->setHighStop(link.maxLimit());
00573         slider->setStopRestitution(0.2);
00574   
00575         // now attach a Motor to drive the joint
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); // provide a little damping
00587 
00588   } // for each link 
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))); //!!! no geom yet
00601   
00602   
00603   // first construct the joint parameter vector q, based on the home positions of 
00604   //  each joint represented in the chain
00605   Assert(chain.size() > 0);
00606   Vector q(chain.dof());
00607   
00608   // note: this only works for links with 1-dof (!!!)
00609   for(Int j=0; j<chain.dof(); j++) { // for each joint
00610     const KinematicChain::Link& link(chain.linkOfVariable(j)); // get link for this joint
00611     q[j] = link.variable();
00612   }
00613 
00614   // compute the various transform matrices we need
00615   TransformInfo transformInfo( computeLinkTransforms(mountConfiguration, q) );
00616 
00617   positionLinks(transformInfo);
00618   
00619   if (dynamic) 
00620     attachJoints(transformInfo);
00621 
00622   if (!dynamic) {
00623 //!!! appropriate place for this?? (note another one in SimulatedSerialManipulator)    
00624     // replace the default CollisionResponseHandler with one that
00625     // doesn't create contacts
00626     ref<CollisionResponseHandler> nullHandler(NewObj NullCollisionResponseHandler(solidSystem->getCollisionDetector()));
00627     solidSystem->setCollisionResponseHandler( nullHandler );
00628   }
00629 
00630   // now create a CollisionResponseHandler to handle collisions between
00631   //  the proximity CollidableBodies and oher objects and insert it into
00632   //  the collision chain before the final handler
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 // Spatial
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] ); // first joint params
00690 
00691   Assert(firstSolid);
00692   Assert(manipEESolid);
00693 
00694   if (dynamic) {
00695   
00696     // attach using a FixedConstraint
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   } // if dynamic
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 base::Point3 SimulatedTool::getEEPosition() const
00738 {
00739   // the end-effector frame is co-incident with the end of the ee solid
00740 
00741   // get the vector offset from ee origin to ee solid origin
00742   Vector3 eeToEESolidOffset( eeToEESolid.getTranslation() );
00743   // now express it in the world frame
00744   Vector3 eeToEESolidOffsetWorld( endSolid->getOrientation().rotate(eeToEESolidOffset) );
00745   // add it to the end solid origin to get the ee origin
00746 
00747   return endSolid->getPosition() + eeToEESolidOffsetWorld;
00748 }
00749 
00750 
00751 base::Orient SimulatedTool::getEEOrientation() const
00752 {
00753   Matrix3 eeToEESolidOrient(eeToEESolid.getRotation());
00754   return base::Orient(  endSolid->getOrientation() * Orient(eeToEESolidOrient).getQuat4() );
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()); // collidables for each link
00770   proximityCollidables.resize(links.size());  // proximity sensor for each link
00771   ref<CollidableGroup> linkCollidableGroup = cc->createCollidableGroup();
00772   proximityCollidableGroup = cc->createCollidableGroup();
00773 
00774   // create two Collidables for each link (one that is connected to the Solid
00775   //  and one for the proximity sensor)
00776   for(Int l=1; l<=chain.size(); l++) {
00777     // Collidable for link Solid
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     // cylinder Collidable for proximity around each link
00784     ref<const Shape> linkShape( links[l]->getShape() );
00785     Dimension3 e = narrow_ref<const Box>(linkShape)->dimensions()/2.0; // link Box extent
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); // the link solid is normally inside the proximity Collidable
00793     pbody->setUserClass(SensorCollidableClass); // cull sensor-sensor collision checks
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     // ref self so we can identify our Collidable quickly in ProximityCollisionResponseHandler
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 //  Debugln(Tmp,"here lp.size=" << linkProximity.size());
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   // figure out proximity info for ControlInterface
00862 
00863   bool firstIsSensor = (collisionState->collidable1->getUserData() == ref<SimulatedTool>(this));
00864   
00865   // find the corresponding link
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 //!!!Debugln(DJ,"collision: " << body1->getName() << " and " << body2->getName());  
00881   
00882 
00883   // now we compute the distance from the axis of the Solid (actually a segment
00884   //  running along the axis) and the obstacle
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   //  now determine distance between the obstacle and the link segment
00891   ref<const Shape> obstacleShape( (firstIsSensor?body2:body1)->getShape() );
00892   Transform obstacleT( (firstIsSensor?body2:body1)->getConfiguration() );
00893   // shortest degment between them
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 //!!! debug  
00906   VisualDebugUtil::setColor(body1->getName(), Color4("red",0.4)); 
00907 
00908 }
00909 

Generated on Thu Jul 29 15:56:43 2004 for OpenSim by doxygen 1.3.6