$search
00001 /********************************************************************* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2010, University of Tokyo 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redstributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of the Willow Garage nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 *********************************************************************/ 00034 00035 /* Author: Rosen Diankov, used OpenRAVE files for reference */ 00036 #include <vector> 00037 #include <list> 00038 #include <map> 00039 #include <stdint.h> 00040 #include <cstdlib> 00041 #include <cmath> 00042 #include <string> 00043 #include <sstream> 00044 00045 #include <dae.h> 00046 #include <dae/daeErrorHandler.h> 00047 #include <dom/domCOLLADA.h> 00048 #include <dae/domAny.h> 00049 #include <dom/domConstants.h> 00050 #include <dom/domTriangles.h> 00051 #include <dae/daeStandardURIResolver.h> 00052 00053 #include <boost/assert.hpp> 00054 #include <boost/format.hpp> 00055 #include <boost/shared_ptr.hpp> 00056 00057 #include <ros/ros.h> 00058 #include <collada_parser/collada_parser.h> 00059 #include <urdf_interface/model.h> 00060 00061 #ifndef HAVE_MKSTEMPS 00062 #include <fstream> 00063 #include <fcntl.h> 00064 #endif 00065 #ifndef HAVE_MKSTEMPS 00066 #include <fstream> 00067 #include <fcntl.h> 00068 #endif 00069 00070 #define FOREACH(it, v) for(typeof((v).begin())it = (v).begin(); it != (v).end(); (it)++) 00071 #define FOREACHC FOREACH 00072 00073 namespace urdf { 00074 00075 00076 class UnlinkFilename 00077 { 00078 public: 00079 UnlinkFilename(const std::string& filename) : _filename(filename) { 00080 } 00081 virtual ~UnlinkFilename() { 00082 unlink(_filename.c_str()); 00083 } 00084 std::string _filename; 00085 }; 00086 static std::list<boost::shared_ptr<UnlinkFilename> > _listTempFilenames; 00087 00088 class ColladaModelReader : public daeErrorHandler 00089 { 00090 00091 class JointAxisBinding 00092 { 00093 public: 00094 JointAxisBinding(daeElementRef pvisualtrans, domAxis_constraintRef pkinematicaxis, domCommon_float_or_paramRef jointvalue, domKinematics_axis_infoRef kinematics_axis_info, domMotion_axis_infoRef motion_axis_info) : pvisualtrans(pvisualtrans), pkinematicaxis(pkinematicaxis), jointvalue(jointvalue), kinematics_axis_info(kinematics_axis_info), motion_axis_info(motion_axis_info) { 00095 BOOST_ASSERT( !!pkinematicaxis ); 00096 daeElement* pae = pvisualtrans->getParentElement(); 00097 while (!!pae) { 00098 visualnode = daeSafeCast<domNode> (pae); 00099 if (!!visualnode) { 00100 break; 00101 } 00102 pae = pae->getParentElement(); 00103 } 00104 00105 if (!visualnode) { 00106 ROS_WARN_STREAM(str(boost::format("couldn't find parent node of element id %s, sid %s\n")%pkinematicaxis->getID()%pkinematicaxis->getSid())); 00107 } 00108 } 00109 00110 daeElementRef pvisualtrans; 00111 domAxis_constraintRef pkinematicaxis; 00112 domCommon_float_or_paramRef jointvalue; 00113 domNodeRef visualnode; 00114 domKinematics_axis_infoRef kinematics_axis_info; 00115 domMotion_axis_infoRef motion_axis_info; 00116 }; 00117 00119 class LinkBinding 00120 { 00121 public: 00122 domNodeRef node; 00123 domLinkRef domlink; 00124 domInstance_rigid_bodyRef irigidbody; 00125 domRigid_bodyRef rigidbody; 00126 domNodeRef nodephysicsoffset; 00127 }; 00128 00130 class KinematicsSceneBindings 00131 { 00132 public: 00133 std::list< std::pair<domNodeRef,domInstance_kinematics_modelRef> > listKinematicsVisualBindings; 00134 std::list<JointAxisBinding> listAxisBindings; 00135 std::list<LinkBinding> listLinkBindings; 00136 00137 bool AddAxisInfo(const domInstance_kinematics_model_Array& arr, domKinematics_axis_infoRef kinematics_axis_info, domMotion_axis_infoRef motion_axis_info) 00138 { 00139 if( !kinematics_axis_info ) { 00140 return false; 00141 } 00142 for(size_t ik = 0; ik < arr.getCount(); ++ik) { 00143 daeElement* pelt = daeSidRef(kinematics_axis_info->getAxis(), arr[ik]->getUrl().getElement()).resolve().elt; 00144 if( !!pelt ) { 00145 // look for the correct placement 00146 bool bfound = false; 00147 FOREACH(itbinding,listAxisBindings) { 00148 if( itbinding->pkinematicaxis.cast() == pelt ) { 00149 itbinding->kinematics_axis_info = kinematics_axis_info; 00150 if( !!motion_axis_info ) { 00151 itbinding->motion_axis_info = motion_axis_info; 00152 } 00153 bfound = true; 00154 break; 00155 } 00156 } 00157 if( !bfound ) { 00158 ROS_WARN_STREAM(str(boost::format("could not find binding for axis: %s, %s\n")%kinematics_axis_info->getAxis()%pelt->getAttribute("sid"))); 00159 return false; 00160 } 00161 return true; 00162 } 00163 } 00164 ROS_WARN_STREAM(str(boost::format("could not find kinematics axis target: %s\n")%kinematics_axis_info->getAxis())); 00165 return false; 00166 } 00167 }; 00168 00169 struct USERDATA 00170 { 00171 USERDATA() { 00172 } 00173 USERDATA(double scale) : scale(scale) { 00174 } 00175 double scale; 00176 boost::shared_ptr<void> p; 00177 }; 00178 00179 enum GeomType { 00180 GeomNone = 0, 00181 GeomBox = 1, 00182 GeomSphere = 2, 00183 GeomCylinder = 3, 00184 GeomTrimesh = 4, 00185 }; 00186 00187 struct GEOMPROPERTIES 00188 { 00189 Pose _t; 00190 Vector3 vGeomData; 00191 00192 00193 00194 Color diffuseColor, ambientColor; 00195 std::vector<Vector3> vertices; 00196 std::vector<int> indices; 00197 00199 GeomType type; 00200 00201 00202 // generate a sphere triangulation starting with an icosahedron 00203 // all triangles are oriented counter clockwise 00204 static void GenerateSphereTriangulation(std::vector<Vector3> realvertices, std::vector<int> realindices, int levels) 00205 { 00206 const double GTS_M_ICOSAHEDRON_X = 0.850650808352039932181540497063011072240401406; 00207 const double GTS_M_ICOSAHEDRON_Y = 0.525731112119133606025669084847876607285497935; 00208 const double GTS_M_ICOSAHEDRON_Z = 0; 00209 std::vector<Vector3> tempvertices[2]; 00210 std::vector<int> tempindices[2]; 00211 00212 tempvertices[0].push_back(Vector3(+GTS_M_ICOSAHEDRON_Z, +GTS_M_ICOSAHEDRON_X, -GTS_M_ICOSAHEDRON_Y)); 00213 tempvertices[0].push_back(Vector3(+GTS_M_ICOSAHEDRON_X, +GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z)); 00214 tempvertices[0].push_back(Vector3(+GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z, -GTS_M_ICOSAHEDRON_X)); 00215 tempvertices[0].push_back(Vector3(+GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z, +GTS_M_ICOSAHEDRON_X)); 00216 tempvertices[0].push_back(Vector3(+GTS_M_ICOSAHEDRON_X, -GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z)); 00217 tempvertices[0].push_back(Vector3(+GTS_M_ICOSAHEDRON_Z, +GTS_M_ICOSAHEDRON_X, +GTS_M_ICOSAHEDRON_Y)); 00218 tempvertices[0].push_back(Vector3(-GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z, +GTS_M_ICOSAHEDRON_X)); 00219 tempvertices[0].push_back(Vector3(+GTS_M_ICOSAHEDRON_Z, -GTS_M_ICOSAHEDRON_X, -GTS_M_ICOSAHEDRON_Y)); 00220 tempvertices[0].push_back(Vector3(-GTS_M_ICOSAHEDRON_X, +GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z)); 00221 tempvertices[0].push_back(Vector3(-GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z, -GTS_M_ICOSAHEDRON_X)); 00222 tempvertices[0].push_back(Vector3(-GTS_M_ICOSAHEDRON_X, -GTS_M_ICOSAHEDRON_Y, +GTS_M_ICOSAHEDRON_Z)); 00223 tempvertices[0].push_back(Vector3(+GTS_M_ICOSAHEDRON_Z, -GTS_M_ICOSAHEDRON_X, +GTS_M_ICOSAHEDRON_Y)); 00224 00225 const int nindices=60; 00226 int indices[nindices] = { 00227 0, 1, 2, 00228 1, 3, 4, 00229 3, 5, 6, 00230 2, 4, 7, 00231 5, 6, 8, 00232 2, 7, 9, 00233 0, 5, 8, 00234 7, 9, 10, 00235 0, 1, 5, 00236 7, 10, 11, 00237 1, 3, 5, 00238 6, 10, 11, 00239 3, 6, 11, 00240 9, 10, 8, 00241 3, 4, 11, 00242 6, 8, 10, 00243 4, 7, 11, 00244 1, 2, 4, 00245 0, 8, 9, 00246 0, 2, 9 00247 }; 00248 00249 Vector3 v[3]; 00250 // make sure oriented CCW 00251 for(int i = 0; i < nindices; i += 3 ) { 00252 v[0] = tempvertices[0][indices[i]]; 00253 v[1] = tempvertices[0][indices[i+1]]; 00254 v[2] = tempvertices[0][indices[i+2]]; 00255 if( _dot3(v[0], _cross3(_sub3(v[1],v[0]),_sub3(v[2],v[0]))) < 0 ) { 00256 std::swap(indices[i], indices[i+1]); 00257 } 00258 } 00259 00260 tempindices[0].resize(nindices); 00261 std::copy(&indices[0],&indices[nindices],tempindices[0].begin()); 00262 std::vector<Vector3>* curvertices = &tempvertices[0], *newvertices = &tempvertices[1]; 00263 std::vector<int> *curindices = &tempindices[0], *newindices = &tempindices[1]; 00264 while(levels-- > 0) { 00265 00266 newvertices->resize(0); 00267 newvertices->reserve(2*curvertices->size()); 00268 newvertices->insert(newvertices->end(), curvertices->begin(), curvertices->end()); 00269 newindices->resize(0); 00270 newindices->reserve(4*curindices->size()); 00271 00272 std::map< uint64_t, int > mapnewinds; 00273 std::map< uint64_t, int >::iterator it; 00274 00275 for(size_t i = 0; i < curindices->size(); i += 3) { 00276 // for ever tri, create 3 new vertices and 4 new triangles. 00277 v[0] = curvertices->at(curindices->at(i)); 00278 v[1] = curvertices->at(curindices->at(i+1)); 00279 v[2] = curvertices->at(curindices->at(i+2)); 00280 00281 int inds[3]; 00282 for(int j = 0; j < 3; ++j) { 00283 uint64_t key = ((uint64_t)curindices->at(i+j)<<32)|(uint64_t)curindices->at(i + ((j+1)%3)); 00284 it = mapnewinds.find(key); 00285 00286 if( it == mapnewinds.end() ) { 00287 inds[j] = mapnewinds[key] = mapnewinds[(key<<32)|(key>>32)] = (int)newvertices->size(); 00288 newvertices->push_back(_normalize3(_add3(v[j],v[(j+1)%3 ]))); 00289 } 00290 else { 00291 inds[j] = it->second; 00292 } 00293 } 00294 00295 newindices->push_back(curindices->at(i)); newindices->push_back(inds[0]); newindices->push_back(inds[2]); 00296 newindices->push_back(inds[0]); newindices->push_back(curindices->at(i+1)); newindices->push_back(inds[1]); 00297 newindices->push_back(inds[2]); newindices->push_back(inds[0]); newindices->push_back(inds[1]); 00298 newindices->push_back(inds[2]); newindices->push_back(inds[1]); newindices->push_back(curindices->at(i+2)); 00299 } 00300 00301 std::swap(newvertices,curvertices); 00302 std::swap(newindices,curindices); 00303 } 00304 00305 realvertices = *curvertices; 00306 realindices = *curindices; 00307 } 00308 00309 bool InitCollisionMesh(double fTessellation=1.0) 00310 { 00311 if( type == GeomTrimesh ) { 00312 return true; 00313 } 00314 indices.clear(); 00315 vertices.clear(); 00316 00317 if( fTessellation < 0.01f ) { 00318 fTessellation = 0.01f; 00319 } 00320 // start tesselating 00321 switch(type) { 00322 case GeomSphere: { 00323 // log_2 (1+ tess) 00324 GenerateSphereTriangulation(vertices,indices, 3 + (int)(logf(fTessellation) / logf(2.0f)) ); 00325 double fRadius = vGeomData.x; 00326 FOREACH(it, vertices) { 00327 it->x *= fRadius; 00328 it->y *= fRadius; 00329 it->z *= fRadius; 00330 } 00331 break; 00332 } 00333 case GeomBox: { 00334 // trivial 00335 Vector3 ex = vGeomData; 00336 Vector3 v[8] = { Vector3(ex.x, ex.y, ex.z), 00337 Vector3(ex.x, ex.y, -ex.z), 00338 Vector3(ex.x, -ex.y, ex.z), 00339 Vector3(ex.x, -ex.y, -ex.z), 00340 Vector3(-ex.x, ex.y, ex.z), 00341 Vector3(-ex.x, ex.y, -ex.z), 00342 Vector3(-ex.x, -ex.y, ex.z), 00343 Vector3(-ex.x, -ex.y, -ex.z) }; 00344 const int nindices = 36; 00345 int startindices[] = { 00346 0, 1, 2, 00347 1, 2, 3, 00348 4, 5, 6, 00349 5, 6, 7, 00350 0, 1, 4, 00351 1, 4, 5, 00352 2, 3, 6, 00353 3, 6, 7, 00354 0, 2, 4, 00355 2, 4, 6, 00356 1, 3, 5, 00357 3, 5, 7 00358 }; 00359 00360 for(int i = 0; i < nindices; i += 3 ) { 00361 Vector3 v1 = v[startindices[i]]; 00362 Vector3 v2 = v[startindices[i+1]]; 00363 Vector3 v3 = v[startindices[i+2]]; 00364 if( _dot3(v1, _sub3(v2,_cross3(v1, _sub3(v3,v1)))) < 0 ) { 00365 std::swap(indices[i], indices[i+1]); 00366 } 00367 } 00368 00369 vertices.resize(8); 00370 std::copy(&v[0],&v[8],vertices.begin()); 00371 indices.resize(nindices); 00372 std::copy(&startindices[0],&startindices[nindices],indices.begin()); 00373 break; 00374 } 00375 case GeomCylinder: { 00376 // cylinder is on y axis 00377 double rad = vGeomData.x, len = vGeomData.y*0.5f; 00378 00379 int numverts = (int)(fTessellation*24.0f) + 3; 00380 double dtheta = 2 * M_PI / (double)numverts; 00381 vertices.push_back(Vector3(0,0,len)); 00382 vertices.push_back(Vector3(0,0,-len)); 00383 vertices.push_back(Vector3(rad,0,len)); 00384 vertices.push_back(Vector3(rad,0,-len)); 00385 00386 for(int i = 0; i < numverts+1; ++i) { 00387 double s = rad * std::sin(dtheta * (double)i); 00388 double c = rad * std::cos(dtheta * (double)i); 00389 00390 int off = (int)vertices.size(); 00391 vertices.push_back(Vector3(c, s, len)); 00392 vertices.push_back(Vector3(c, s, -len)); 00393 00394 indices.push_back(0); indices.push_back(off); indices.push_back(off-2); 00395 indices.push_back(1); indices.push_back(off-1); indices.push_back(off+1); 00396 indices.push_back(off-2); indices.push_back(off); indices.push_back(off-1); 00397 indices.push_back(off); indices.push_back(off-1); indices.push_back(off+1); 00398 } 00399 break; 00400 } 00401 default: 00402 BOOST_ASSERT(0); 00403 } 00404 return true; 00405 } 00406 }; 00407 00408 public: 00409 ColladaModelReader(boost::shared_ptr<ModelInterface> model) : _dom(NULL), _nGlobalSensorId(0), _nGlobalManipulatorId(0), _model(model) { 00410 daeErrorHandler::setErrorHandler(this); 00411 _resourcedir = "."; 00412 _collada = new DAE(); 00413 } 00414 virtual ~ColladaModelReader() { 00415 _vuserdata.clear(); 00416 //delete _collada; 00417 } 00418 00419 bool InitFromFile(const std::string& filename) { 00420 ROS_DEBUG_STREAM(str(boost::format("init COLLADA reader version: %s, namespace: %s, filename: %s\n")%COLLADA_VERSION%COLLADA_NAMESPACE%filename)); 00421 _dom = _collada->open(filename); 00422 if (!_dom) { 00423 return false; 00424 } 00425 _filename=filename; 00426 00427 size_t maxchildren = _countChildren(_dom); 00428 _vuserdata.resize(0); 00429 _vuserdata.reserve(maxchildren); 00430 00431 double dScale = 1.0; 00432 _processUserData(_dom, dScale); 00433 ROS_DEBUG_STREAM(str(boost::format("processed children: %d/%d\n")%_vuserdata.size()%maxchildren)); 00434 return _Extract(); 00435 } 00436 00437 bool InitFromData(const std::string& pdata) { 00438 ROS_DEBUG_STREAM(str(boost::format("init COLLADA reader version: %s, namespace: %s\n")%COLLADA_VERSION%COLLADA_NAMESPACE)); 00439 _dom = _collada->openFromMemory(".",pdata.c_str()); 00440 if (!_dom) { 00441 return false; 00442 } 00443 00444 size_t maxchildren = _countChildren(_dom); 00445 _vuserdata.resize(0); 00446 _vuserdata.reserve(maxchildren); 00447 00448 double dScale = 1.0; 00449 _processUserData(_dom, dScale); 00450 ROS_DEBUG_STREAM(str(boost::format("processed children: %d/%d\n")%_vuserdata.size()%maxchildren)); 00451 return _Extract(); 00452 } 00453 00454 protected: 00455 00457 bool _Extract() 00458 { 00459 _model->clear(); 00460 std::list< std::pair<domInstance_kinematics_modelRef, boost::shared_ptr<KinematicsSceneBindings> > > listPossibleBodies; 00461 domCOLLADA::domSceneRef allscene = _dom->getScene(); 00462 if( !allscene ) { 00463 return false; 00464 } 00465 00466 // parse each instance kinematics scene, prioritize real robots 00467 for (size_t iscene = 0; iscene < allscene->getInstance_kinematics_scene_array().getCount(); iscene++) { 00468 domInstance_kinematics_sceneRef kiscene = allscene->getInstance_kinematics_scene_array()[iscene]; 00469 domKinematics_sceneRef kscene = daeSafeCast<domKinematics_scene> (kiscene->getUrl().getElement().cast()); 00470 if (!kscene) { 00471 continue; 00472 } 00473 boost::shared_ptr<KinematicsSceneBindings> bindings(new KinematicsSceneBindings()); 00474 _ExtractKinematicsVisualBindings(allscene->getInstance_visual_scene(),kiscene,*bindings); 00475 _ExtractPhysicsBindings(allscene,*bindings); 00476 for(size_t ias = 0; ias < kscene->getInstance_articulated_system_array().getCount(); ++ias) { 00477 if( _ExtractArticulatedSystem(kscene->getInstance_articulated_system_array()[ias], *bindings) ) { 00478 _PostProcess(); 00479 return true; 00480 } 00481 } 00482 for(size_t ikmodel = 0; ikmodel < kscene->getInstance_kinematics_model_array().getCount(); ++ikmodel) { 00483 listPossibleBodies.push_back(std::make_pair(kscene->getInstance_kinematics_model_array()[ikmodel], bindings)); 00484 } 00485 } 00486 00487 FOREACH(it, listPossibleBodies) { 00488 if( _ExtractKinematicsModel(it->first, *it->second) ) { 00489 _PostProcess(); 00490 return true; 00491 } 00492 } 00493 00494 return false; 00495 } 00496 00497 void _PostProcess() 00498 { 00499 std::map<std::string, std::string> parent_link_tree; 00500 // building tree: name mapping 00501 if (!_model->initTree(parent_link_tree)) { 00502 ROS_ERROR("failed to build tree"); 00503 } 00504 00505 // find the root link 00506 if (!_model->initRoot(parent_link_tree)) { 00507 ROS_ERROR("failed to find root link"); 00508 } 00509 } 00510 00512 bool _ExtractArticulatedSystem(domInstance_articulated_systemRef ias, KinematicsSceneBindings& bindings) 00513 { 00514 if( !ias ) { 00515 return false; 00516 } 00517 ROS_DEBUG_STREAM(str(boost::format("instance articulated system sid %s\n")%ias->getSid())); 00518 domArticulated_systemRef articulated_system = daeSafeCast<domArticulated_system> (ias->getUrl().getElement().cast()); 00519 if( !articulated_system ) { 00520 return false; 00521 } 00522 00523 boost::shared_ptr<std::string> pinterface_type = _ExtractInterfaceType(ias->getExtra_array()); 00524 if( !pinterface_type ) { 00525 pinterface_type = _ExtractInterfaceType(articulated_system->getExtra_array()); 00526 } 00527 if( !!pinterface_type ) { 00528 ROS_DEBUG_STREAM(str(boost::format("robot type: %s")%(*pinterface_type))); 00529 } 00530 00531 // set the name 00532 if( _model->name_.size() == 0 && !!ias->getName() ) { 00533 _model->name_ = ias->getName(); 00534 } 00535 if( _model->name_.size() == 0 && !!ias->getSid()) { 00536 _model->name_ = ias->getSid(); 00537 } 00538 if( _model->name_.size() == 0 && !!articulated_system->getName() ) { 00539 _model->name_ = articulated_system->getName(); 00540 } 00541 if( _model->name_.size() == 0 && !!articulated_system->getId()) { 00542 _model->name_ = articulated_system->getId(); 00543 } 00544 00545 if( !!articulated_system->getMotion() ) { 00546 domInstance_articulated_systemRef ias_new = articulated_system->getMotion()->getInstance_articulated_system(); 00547 if( !!articulated_system->getMotion()->getTechnique_common() ) { 00548 for(size_t i = 0; i < articulated_system->getMotion()->getTechnique_common()->getAxis_info_array().getCount(); ++i) { 00549 domMotion_axis_infoRef motion_axis_info = articulated_system->getMotion()->getTechnique_common()->getAxis_info_array()[i]; 00550 // this should point to a kinematics axis_info 00551 domKinematics_axis_infoRef kinematics_axis_info = daeSafeCast<domKinematics_axis_info>(daeSidRef(motion_axis_info->getAxis(), ias_new->getUrl().getElement()).resolve().elt); 00552 if( !!kinematics_axis_info ) { 00553 // find the parent kinematics and go through all its instance kinematics models 00554 daeElement* pparent = kinematics_axis_info->getParent(); 00555 while(!!pparent && pparent->typeID() != domKinematics::ID()) { 00556 pparent = pparent->getParent(); 00557 } 00558 BOOST_ASSERT(!!pparent); 00559 bindings.AddAxisInfo(daeSafeCast<domKinematics>(pparent)->getInstance_kinematics_model_array(), kinematics_axis_info, motion_axis_info); 00560 } 00561 else { 00562 ROS_WARN_STREAM(str(boost::format("failed to find kinematics axis %s\n")%motion_axis_info->getAxis())); 00563 } 00564 } 00565 } 00566 if( !_ExtractArticulatedSystem(ias_new,bindings) ) { 00567 return false; 00568 } 00569 } 00570 else { 00571 if( !articulated_system->getKinematics() ) { 00572 ROS_WARN_STREAM(str(boost::format("collada <kinematics> tag empty? instance_articulated_system=%s\n")%ias->getID())); 00573 return true; 00574 } 00575 00576 if( !!articulated_system->getKinematics()->getTechnique_common() ) { 00577 for(size_t i = 0; i < articulated_system->getKinematics()->getTechnique_common()->getAxis_info_array().getCount(); ++i) { 00578 bindings.AddAxisInfo(articulated_system->getKinematics()->getInstance_kinematics_model_array(), articulated_system->getKinematics()->getTechnique_common()->getAxis_info_array()[i], NULL); 00579 } 00580 } 00581 00582 for(size_t ik = 0; ik < articulated_system->getKinematics()->getInstance_kinematics_model_array().getCount(); ++ik) { 00583 _ExtractKinematicsModel(articulated_system->getKinematics()->getInstance_kinematics_model_array()[ik],bindings); 00584 } 00585 } 00586 00587 _ExtractRobotManipulators(articulated_system); 00588 _ExtractRobotAttachedSensors(articulated_system); 00589 return true; 00590 } 00591 00592 bool _ExtractKinematicsModel(domInstance_kinematics_modelRef ikm, KinematicsSceneBindings& bindings) 00593 { 00594 if( !ikm ) { 00595 return false; 00596 } 00597 ROS_DEBUG_STREAM(str(boost::format("instance kinematics model sid %s\n")%ikm->getSid())); 00598 domKinematics_modelRef kmodel = daeSafeCast<domKinematics_model> (ikm->getUrl().getElement().cast()); 00599 if (!kmodel) { 00600 ROS_WARN_STREAM(str(boost::format("%s does not reference valid kinematics\n")%ikm->getSid())); 00601 return false; 00602 } 00603 domPhysics_modelRef pmodel; 00604 boost::shared_ptr<std::string> pinterface_type = _ExtractInterfaceType(ikm->getExtra_array()); 00605 if( !pinterface_type ) { 00606 pinterface_type = _ExtractInterfaceType(kmodel->getExtra_array()); 00607 } 00608 if( !!pinterface_type ) { 00609 ROS_DEBUG_STREAM(str(boost::format("kinbody interface type: %s")%(*pinterface_type))); 00610 } 00611 00612 // find matching visual node 00613 domNodeRef pvisualnode; 00614 FOREACH(it, bindings.listKinematicsVisualBindings) { 00615 if( it->second == ikm ) { 00616 pvisualnode = it->first; 00617 break; 00618 } 00619 } 00620 if( !pvisualnode ) { 00621 ROS_WARN_STREAM(str(boost::format("failed to find visual node for instance kinematics model %s\n")%ikm->getSid())); 00622 return false; 00623 } 00624 00625 if( _model->name_.size() == 0 && !!ikm->getName() ) { 00626 _model->name_ = ikm->getName(); 00627 } 00628 if( _model->name_.size() == 0 && !!ikm->getID() ) { 00629 _model->name_ = ikm->getID(); 00630 } 00631 00632 if (!_ExtractKinematicsModel(kmodel, pvisualnode, pmodel, bindings)) { 00633 ROS_WARN_STREAM(str(boost::format("failed to load kinbody from kinematics model %s\n")%kmodel->getID())); 00634 return false; 00635 } 00636 return true; 00637 } 00638 00640 bool _ExtractKinematicsModel(domKinematics_modelRef kmodel, domNodeRef pnode, domPhysics_modelRef pmodel, const KinematicsSceneBindings& bindings) 00641 { 00642 std::vector<domJointRef> vdomjoints; 00643 ROS_DEBUG_STREAM(str(boost::format("kinematics model: %s\n")%_model->name_)); 00644 if( !!pnode ) { 00645 ROS_DEBUG_STREAM(str(boost::format("node name: %s\n")%pnode->getId())); 00646 } 00647 00648 // Process joint of the kinbody 00649 domKinematics_model_techniqueRef ktec = kmodel->getTechnique_common(); 00650 00651 // Store joints 00652 for (size_t ijoint = 0; ijoint < ktec->getJoint_array().getCount(); ++ijoint) { 00653 vdomjoints.push_back(ktec->getJoint_array()[ijoint]); 00654 } 00655 00656 // Store instances of joints 00657 for (size_t ijoint = 0; ijoint < ktec->getInstance_joint_array().getCount(); ++ijoint) { 00658 domJointRef pelt = daeSafeCast<domJoint> (ktec->getInstance_joint_array()[ijoint]->getUrl().getElement()); 00659 if (!pelt) { 00660 ROS_WARN_STREAM("failed to get joint from instance\n"); 00661 } 00662 else { 00663 vdomjoints.push_back(pelt); 00664 } 00665 } 00666 00667 ROS_DEBUG_STREAM(str(boost::format("Number of root links in the kmodel %d\n")%ktec->getLink_array().getCount())); 00668 for (size_t ilink = 0; ilink < ktec->getLink_array().getCount(); ++ilink) { 00669 _ExtractLink(ktec->getLink_array()[ilink], ilink == 0 ? pnode : domNodeRef(), Pose(), Pose(), vdomjoints, bindings); 00670 } 00671 00672 // TODO: implement mathml 00673 for (size_t iform = 0; iform < ktec->getFormula_array().getCount(); ++iform) { 00674 domFormulaRef pf = ktec->getFormula_array()[iform]; 00675 if (!pf->getTarget()) { 00676 ROS_WARN_STREAM("formula target not valid\n"); 00677 continue; 00678 } 00679 00680 // find the target joint 00681 boost::shared_ptr<Joint> pjoint = _getJointFromRef(pf->getTarget()->getParam()->getValue(),pf); 00682 if (!pjoint) { 00683 continue; 00684 } 00685 00686 if (!!pf->getTechnique_common()) { 00687 daeElementRef peltmath; 00688 daeTArray<daeElementRef> children; 00689 pf->getTechnique_common()->getChildren(children); 00690 for (size_t ichild = 0; ichild < children.getCount(); ++ichild) { 00691 daeElementRef pelt = children[ichild]; 00692 if (_checkMathML(pelt,std::string("math")) ) { 00693 peltmath = pelt; 00694 } 00695 else { 00696 ROS_WARN_STREAM(str(boost::format("unsupported formula element: %s\n")%pelt->getElementName())); 00697 } 00698 } 00699 if (!!peltmath) { 00700 // full math xml spec not supported, only looking for ax+b pattern: 00701 // <apply> <plus/> <apply> <times/> <ci>a</ci> x </apply> <ci>b</ci> </apply> 00702 double a = 1, b = 0; 00703 daeElementRef psymboljoint; 00704 BOOST_ASSERT(peltmath->getChildren().getCount()>0); 00705 daeElementRef papplyelt = peltmath->getChildren()[0]; 00706 BOOST_ASSERT(_checkMathML(papplyelt,"apply")); 00707 BOOST_ASSERT(papplyelt->getChildren().getCount()>0); 00708 if( _checkMathML(papplyelt->getChildren()[0],"plus") ) { 00709 BOOST_ASSERT(papplyelt->getChildren().getCount()==3); 00710 daeElementRef pa = papplyelt->getChildren()[1]; 00711 daeElementRef pb = papplyelt->getChildren()[2]; 00712 if( !_checkMathML(papplyelt->getChildren()[1],"apply") ) { 00713 std::swap(pa,pb); 00714 } 00715 if( !_checkMathML(pa,"csymbol") ) { 00716 BOOST_ASSERT(_checkMathML(pa,"apply")); 00717 BOOST_ASSERT(_checkMathML(pa->getChildren()[0],"times")); 00718 if( _checkMathML(pa->getChildren()[1],"csymbol") ) { 00719 psymboljoint = pa->getChildren()[1]; 00720 BOOST_ASSERT(_checkMathML(pa->getChildren()[2],"cn")); 00721 std::stringstream ss(pa->getChildren()[2]->getCharData()); 00722 ss >> a; 00723 } 00724 else { 00725 psymboljoint = pa->getChildren()[2]; 00726 BOOST_ASSERT(_checkMathML(pa->getChildren()[1],"cn")); 00727 std::stringstream ss(pa->getChildren()[1]->getCharData()); 00728 ss >> a; 00729 } 00730 } 00731 else { 00732 psymboljoint = pa; 00733 } 00734 BOOST_ASSERT(_checkMathML(pb,"cn")); 00735 { 00736 std::stringstream ss(pb->getCharData()); 00737 ss >> b; 00738 } 00739 } 00740 else if( _checkMathML(papplyelt->getChildren()[0],"minus") ) { 00741 BOOST_ASSERT(_checkMathML(papplyelt->getChildren()[1],"csymbol")); 00742 a = -1; 00743 psymboljoint = papplyelt->getChildren()[1]; 00744 } 00745 else { 00746 BOOST_ASSERT(_checkMathML(papplyelt->getChildren()[0],"csymbol")); 00747 psymboljoint = papplyelt->getChildren()[0]; 00748 } 00749 BOOST_ASSERT(psymboljoint->hasAttribute("encoding")); 00750 BOOST_ASSERT(psymboljoint->getAttribute("encoding")==std::string("COLLADA")); 00751 boost::shared_ptr<Joint> pbasejoint = _getJointFromRef(psymboljoint->getCharData().c_str(),pf); 00752 if( !!pbasejoint ) { 00753 // set the mimic properties 00754 pjoint->mimic.reset(new JointMimic()); 00755 pjoint->mimic->joint_name = pbasejoint->name; 00756 pjoint->mimic->multiplier = a; 00757 pjoint->mimic->offset = b; 00758 ROS_DEBUG_STREAM(str(boost::format("assigning joint %s to mimic %s %f %f\n")%pjoint->name%pbasejoint->name%a%b)); 00759 } 00760 } 00761 } 00762 } 00763 return true; 00764 } 00765 00767 boost::shared_ptr<Link> _ExtractLink(const domLinkRef pdomlink,const domNodeRef pdomnode, const Pose& tParentWorldLink, const Pose& tParentLink, const std::vector<domJointRef>& vdomjoints, const KinematicsSceneBindings& bindings) { 00768 const std::list<JointAxisBinding>& listAxisBindings = bindings.listAxisBindings; 00769 // Set link name with the name of the COLLADA's Link 00770 std::string linkname = _ExtractLinkName(pdomlink); 00771 if( linkname.size() == 0 ) { 00772 ROS_WARN_STREAM("<link> has no name or id, falling back to <node>!\n"); 00773 if( !!pdomnode ) { 00774 if (!!pdomnode->getName()) { 00775 linkname = pdomnode->getName(); 00776 } 00777 if( linkname.size() == 0 && !!pdomnode->getID()) { 00778 linkname = pdomnode->getID(); 00779 } 00780 } 00781 } 00782 00783 boost::shared_ptr<Link> plink; 00784 _model->getLink(linkname,plink); 00785 if( !plink ) { 00786 plink.reset(new Link()); 00787 plink->name = linkname; 00788 plink->visual.reset(new Visual()); 00789 plink->visual->material_name = ""; 00790 plink->visual->material.reset(new Material()); 00791 plink->visual->material->name = "Red"; 00792 plink->visual->material->color.r = 0.0; 00793 plink->visual->material->color.g = 1.0; 00794 plink->visual->material->color.b = 0.0; 00795 plink->visual->material->color.a = 1.0; 00796 plink->inertial.reset(); 00797 _model->links_.insert(std::make_pair(linkname,plink)); 00798 } 00799 00800 _getUserData(pdomlink)->p = plink; 00801 if( !!pdomnode ) { 00802 ROS_DEBUG_STREAM(str(boost::format("Node Id %s and Name %s\n")%pdomnode->getId()%pdomnode->getName())); 00803 } 00804 00805 // physics 00806 domInstance_rigid_bodyRef irigidbody; 00807 domRigid_bodyRef rigidbody; 00808 bool bFoundBinding = false; 00809 FOREACH(itlinkbinding, bindings.listLinkBindings) { 00810 if( !!pdomnode->getID() && !!itlinkbinding->node->getID() && strcmp(pdomnode->getID(),itlinkbinding->node->getID()) == 0 ) { 00811 bFoundBinding = true; 00812 irigidbody = itlinkbinding->irigidbody; 00813 rigidbody = itlinkbinding->rigidbody; 00814 } 00815 } 00816 00817 if( !!rigidbody && !!rigidbody->getTechnique_common() ) { 00818 domRigid_body::domTechnique_commonRef rigiddata = rigidbody->getTechnique_common(); 00819 if( !!rigiddata->getMass() ) { 00820 if ( !plink->inertial ) { 00821 plink->inertial.reset(new Inertial()); 00822 } 00823 plink->inertial->mass = rigiddata->getMass()->getValue(); 00824 } 00825 if( !!rigiddata->getInertia() ) { 00826 if ( !plink->inertial ) { 00827 plink->inertial.reset(new Inertial()); 00828 } 00829 plink->inertial->ixx = rigiddata->getInertia()->getValue()[0]; 00830 plink->inertial->iyy = rigiddata->getInertia()->getValue()[1]; 00831 plink->inertial->izz = rigiddata->getInertia()->getValue()[2]; 00832 } 00833 if( !!rigiddata->getMass_frame() ) { 00834 if ( !plink->inertial ) { 00835 plink->inertial.reset(new Inertial()); 00836 } 00837 plink->inertial->origin = _poseMult(_poseInverse(tParentWorldLink), _poseFromMatrix(_ExtractFullTransform(rigiddata->getMass_frame()))); 00838 } 00839 } 00840 00841 00842 std::list<GEOMPROPERTIES> listGeomProperties; 00843 if (!pdomlink) { 00844 ROS_WARN_STREAM("Extract object NOT kinematics !!!\n"); 00845 _ExtractGeometry(pdomnode,listGeomProperties,listAxisBindings,Pose()); 00846 } 00847 else { 00848 ROS_DEBUG_STREAM(str(boost::format("Attachment link elements: %d\n")%pdomlink->getAttachment_full_array().getCount())); 00849 Pose tlink = _poseFromMatrix(_ExtractFullTransform(pdomlink)); 00850 plink->visual->origin = _poseMult(tParentLink, tlink); // use the kinematics coordinate system for each link 00851 // ROS_INFO("link %s rot: %f %f %f %f",linkname.c_str(),plink->visual->origin.rotation.w, plink->visual->origin.rotation.x,plink->visual->origin.rotation.y,plink->visual->origin.rotation.z); 00852 // ROS_INFO("link %s trans: %f %f %f",linkname.c_str(),plink->visual->origin.position.x,plink->visual->origin.position.y,plink->visual->origin.position.z); 00853 00854 // Get the geometry 00855 _ExtractGeometry(pdomnode,listGeomProperties,listAxisBindings,_poseMult(_poseMult(tParentWorldLink,tlink),plink->visual->origin)); 00856 00857 ROS_DEBUG_STREAM(str(boost::format("After ExtractGeometry Attachment link elements: %d\n")%pdomlink->getAttachment_full_array().getCount())); 00858 00859 // Process all atached links 00860 for (size_t iatt = 0; iatt < pdomlink->getAttachment_full_array().getCount(); ++iatt) { 00861 domLink::domAttachment_fullRef pattfull = pdomlink->getAttachment_full_array()[iatt]; 00862 00863 // get link kinematics transformation 00864 Pose tatt = _poseFromMatrix(_ExtractFullTransform(pattfull)); 00865 00866 // process attached links 00867 daeElement* peltjoint = daeSidRef(pattfull->getJoint(), pattfull).resolve().elt; 00868 domJointRef pdomjoint = daeSafeCast<domJoint> (peltjoint); 00869 00870 if (!pdomjoint) { 00871 domInstance_jointRef pdomijoint = daeSafeCast<domInstance_joint> (peltjoint); 00872 if (!!pdomijoint) { 00873 pdomjoint = daeSafeCast<domJoint> (pdomijoint->getUrl().getElement().cast()); 00874 } 00875 } 00876 00877 if (!pdomjoint || pdomjoint->typeID() != domJoint::ID()) { 00878 ROS_WARN_STREAM(str(boost::format("could not find attached joint %s!\n")%pattfull->getJoint())); 00879 return boost::shared_ptr<Link>(); 00880 } 00881 00882 // get direct child link 00883 if (!pattfull->getLink()) { 00884 ROS_WARN_STREAM(str(boost::format("joint %s needs to be attached to a valid link\n")%pdomjoint->getID())); 00885 continue; 00886 } 00887 00888 // find the correct joint in the bindings 00889 daeTArray<domAxis_constraintRef> vdomaxes = pdomjoint->getChildrenByType<domAxis_constraint>(); 00890 domNodeRef pchildnode; 00891 00892 // see if joint has a binding to a visual node 00893 FOREACHC(itaxisbinding,listAxisBindings) { 00894 for (size_t ic = 0; ic < vdomaxes.getCount(); ++ic) { 00895 // If the binding for the joint axis is found, retrieve the info 00896 if (vdomaxes[ic] == itaxisbinding->pkinematicaxis) { 00897 pchildnode = itaxisbinding->visualnode; 00898 break; 00899 } 00900 } 00901 if( !!pchildnode ) { 00902 break; 00903 } 00904 } 00905 if (!pchildnode) { 00906 ROS_DEBUG_STREAM(str(boost::format("joint %s has no visual binding\n")%pdomjoint->getID())); 00907 } 00908 00909 // create the joints before creating the child links 00910 std::vector<boost::shared_ptr<Joint> > vjoints(vdomaxes.getCount()); 00911 for (size_t ic = 0; ic < vdomaxes.getCount(); ++ic) { 00912 bool joint_active = true; // if not active, put into the passive list 00913 FOREACHC(itaxisbinding,listAxisBindings) { 00914 if (vdomaxes[ic] == itaxisbinding->pkinematicaxis) { 00915 if( !!itaxisbinding->kinematics_axis_info ) { 00916 if( !!itaxisbinding->kinematics_axis_info->getActive() ) { 00917 joint_active = resolveBool(itaxisbinding->kinematics_axis_info->getActive(),itaxisbinding->kinematics_axis_info); 00918 } 00919 } 00920 break; 00921 } 00922 } 00923 00924 boost::shared_ptr<Joint> pjoint(new Joint()); 00925 pjoint->limits.reset(new JointLimits()); 00926 pjoint->parent_link_name = plink->name; 00927 00928 if( !!pdomjoint->getName() ) { 00929 pjoint->name = pdomjoint->getName(); 00930 } 00931 else { 00932 pjoint->name = str(boost::format("dummy%d")%_model->joints_.size()); 00933 } 00934 00935 if( !joint_active ) { 00936 ROS_INFO_STREAM(str(boost::format("joint %s is passive, but adding to hierarchy\n")%pjoint->name)); 00937 } 00938 00939 domAxis_constraintRef pdomaxis = vdomaxes[ic]; 00940 if( strcmp(pdomaxis->getElementName(), "revolute") == 0 ) { 00941 pjoint->type = Joint::REVOLUTE; 00942 } 00943 else if( strcmp(pdomaxis->getElementName(), "prismatic") == 0 ) { 00944 pjoint->type = Joint::PRISMATIC; 00945 } 00946 else { 00947 ROS_WARN_STREAM(str(boost::format("unsupported joint type: %s\n")%pdomaxis->getElementName())); 00948 } 00949 00950 _getUserData(pdomjoint)->p = pjoint; 00951 _getUserData(pdomaxis)->p = boost::shared_ptr<int>(new int(_model->joints_.size())); 00952 _model->joints_[pjoint->name] = pjoint; 00953 vjoints[ic] = pjoint; 00954 } 00955 00956 boost::shared_ptr<Link> pchildlink = _ExtractLink(pattfull->getLink(), pchildnode, _poseMult(_poseMult(tParentWorldLink,tlink), tatt), tatt, vdomjoints, bindings); 00957 00958 if (!pchildlink) { 00959 ROS_WARN_STREAM(str(boost::format("Link has no child: %s\n")%plink->name)); 00960 continue; 00961 } 00962 00963 int numjoints = 0; 00964 for (size_t ic = 0; ic < vdomaxes.getCount(); ++ic) { 00965 domKinematics_axis_infoRef kinematics_axis_info; 00966 domMotion_axis_infoRef motion_axis_info; 00967 FOREACHC(itaxisbinding,listAxisBindings) { 00968 bool bfound = false; 00969 if (vdomaxes[ic] == itaxisbinding->pkinematicaxis) { 00970 kinematics_axis_info = itaxisbinding->kinematics_axis_info; 00971 motion_axis_info = itaxisbinding->motion_axis_info; 00972 bfound = true; 00973 break; 00974 } 00975 } 00976 domAxis_constraintRef pdomaxis = vdomaxes[ic]; 00977 if (!pchildlink) { 00978 // create dummy child link 00979 // multiple axes can be easily done with "empty links" 00980 ROS_WARN_STREAM(str(boost::format("creating dummy link %s, num joints %d\n")%plink->name%numjoints)); 00981 00982 std::stringstream ss; 00983 ss << plink->name; 00984 ss <<"_dummy" << numjoints; 00985 pchildlink.reset(new Link()); 00986 pchildlink->name = ss.str(); 00987 _model->links_.insert(std::make_pair(pchildlink->name,pchildlink)); 00988 } 00989 00990 ROS_DEBUG_STREAM(str(boost::format("Joint %s assigned %d \n")%vjoints[ic]->name%ic)); 00991 boost::shared_ptr<Joint> pjoint = vjoints[ic]; 00992 pjoint->child_link_name = pchildlink->name; 00993 00994 // Axes and Anchor assignment. 00995 pjoint->axis.x = pdomaxis->getAxis()->getValue()[0]; 00996 pjoint->axis.y = pdomaxis->getAxis()->getValue()[1]; 00997 pjoint->axis.z = pdomaxis->getAxis()->getValue()[2]; 00998 00999 if (!motion_axis_info) { 01000 ROS_WARN_STREAM(str(boost::format("No motion axis info for joint %s\n")%pjoint->name)); 01001 } 01002 01003 // Sets the Speed and the Acceleration of the joint 01004 if (!!motion_axis_info) { 01005 if (!!motion_axis_info->getSpeed()) { 01006 pjoint->limits->velocity = resolveFloat(motion_axis_info->getSpeed(),motion_axis_info); 01007 ROS_DEBUG("... Joint Speed: %f...\n",pjoint->limits->velocity); 01008 } 01009 if (!!motion_axis_info->getAcceleration()) { 01010 pjoint->limits->effort = resolveFloat(motion_axis_info->getAcceleration(),motion_axis_info); 01011 ROS_DEBUG("... Joint effort: %f...\n",pjoint->limits->effort); 01012 } 01013 } 01014 01015 bool joint_locked = false; // if locked, joint angle is static 01016 bool kinematics_limits = false; 01017 01018 if (!!kinematics_axis_info) { 01019 if (!!kinematics_axis_info->getLocked()) { 01020 joint_locked = resolveBool(kinematics_axis_info->getLocked(),kinematics_axis_info); 01021 } 01022 01023 if (joint_locked) { // If joint is locked set limits to the static value. 01024 if( pjoint->type == Joint::REVOLUTE || pjoint->type ==Joint::PRISMATIC) { 01025 ROS_WARN_STREAM("lock joint!!\n"); 01026 pjoint->limits->lower = 0; 01027 pjoint->limits->upper = 0; 01028 } 01029 } 01030 else if (kinematics_axis_info->getLimits()) { // If there are articulated system kinematics limits 01031 kinematics_limits = true; 01032 double fscale = (pjoint->type == Joint::REVOLUTE) ? (M_PI/180.0f) : _GetUnitScale(kinematics_axis_info); 01033 if( pjoint->type == Joint::REVOLUTE || pjoint->type ==Joint::PRISMATIC) { 01034 pjoint->limits->lower = fscale*(double)(resolveFloat(kinematics_axis_info->getLimits()->getMin(),kinematics_axis_info)); 01035 pjoint->limits->upper = fscale*(double)(resolveFloat(kinematics_axis_info->getLimits()->getMax(),kinematics_axis_info)); 01036 if ( pjoint->limits->lower == 0 && pjoint->limits->upper == 0 ) { 01037 pjoint->type = Joint::FIXED; 01038 } 01039 } 01040 } 01041 } 01042 01043 // Search limits in the joints section 01044 if (!kinematics_axis_info || (!joint_locked && !kinematics_limits)) { 01045 // If there are NO LIMITS 01046 if( !pdomaxis->getLimits() ) { 01047 ROS_DEBUG_STREAM(str(boost::format("There are NO LIMITS in joint %s:%d ...\n")%pjoint->name%kinematics_limits)); 01048 if( pjoint->type == Joint::REVOLUTE ) { 01049 pjoint->type = Joint::CONTINUOUS; // continuous means revolute? 01050 pjoint->limits->lower = -M_PI; 01051 pjoint->limits->upper = M_PI; 01052 } 01053 else { 01054 pjoint->limits->lower = -100000; 01055 pjoint->limits->upper = 100000; 01056 } 01057 } 01058 else { 01059 ROS_DEBUG_STREAM(str(boost::format("There are LIMITS in joint %s ...\n")%pjoint->name)); 01060 double fscale = (pjoint->type == Joint::REVOLUTE) ? (M_PI/180.0f) : _GetUnitScale(pdomaxis); 01061 pjoint->limits->lower = (double)pdomaxis->getLimits()->getMin()->getValue()*fscale; 01062 pjoint->limits->upper = (double)pdomaxis->getLimits()->getMax()->getValue()*fscale; 01063 if ( pjoint->limits->lower == 0 && pjoint->limits->upper == 0 ) { 01064 pjoint->type = Joint::FIXED; 01065 } 01066 } 01067 } 01068 01069 //ROS_INFO("joint %s axis: %f %f %f",pjoint->name.c_str(),pjoint->axis.x,pjoint->axis.y,pjoint->axis.z); 01070 pjoint->parent_to_joint_origin_transform = _poseMult(tatt,_poseFromMatrix(_ExtractFullTransform(pattfull->getLink()))); 01071 pjoint->limits->velocity = pjoint->type == Joint::PRISMATIC ? 0.01 : 0.5f; 01072 pchildlink.reset(); 01073 ++numjoints; 01074 } 01075 } 01076 } 01077 01078 if( pdomlink->getAttachment_start_array().getCount() > 0 ) { 01079 ROS_WARN("urdf collada reader does not support attachment_start\n"); 01080 } 01081 if( pdomlink->getAttachment_end_array().getCount() > 0 ) { 01082 ROS_WARN("urdf collada reader does not support attachment_end\n"); 01083 } 01084 01085 plink->visual->geometry = _CreateGeometry(plink->name, listGeomProperties); 01086 // visual_groups 01087 boost::shared_ptr<std::vector<boost::shared_ptr<Visual > > > viss; 01088 viss.reset(new std::vector<boost::shared_ptr<Visual > >); 01089 viss->push_back(plink->visual); 01090 plink->visual_groups.insert(std::make_pair("default", viss)); 01091 01092 // collision 01093 plink->collision.reset(new Collision()); 01094 plink->collision->geometry = plink->visual->geometry; 01095 plink->collision->origin = plink->visual->origin; 01096 01097 // collision_groups 01098 boost::shared_ptr<std::vector<boost::shared_ptr<Collision > > > cols; 01099 cols.reset(new std::vector<boost::shared_ptr<Collision > >); 01100 cols->push_back(plink->collision); 01101 plink->collision_groups.insert(std::make_pair("default", cols)); 01102 01103 return plink; 01104 } 01105 01106 boost::shared_ptr<Geometry> _CreateGeometry(const std::string& name, const std::list<GEOMPROPERTIES>& listGeomProperties) 01107 { 01108 boost::shared_ptr<Mesh> geometry(new Mesh()); 01109 geometry->type = Geometry::MESH; 01110 geometry->scale.x = 1; 01111 geometry->scale.y = 1; 01112 geometry->scale.z = 1; 01113 01114 std::vector<std::vector<Vector3> > vertices; 01115 std::vector<std::vector<int> > indices; 01116 std::vector<Color> ambients; 01117 std::vector<Color> diffuses; 01118 unsigned int index; 01119 vertices.resize(listGeomProperties.size()); 01120 indices.resize(listGeomProperties.size()); 01121 ambients.resize(listGeomProperties.size()); 01122 diffuses.resize(listGeomProperties.size()); 01123 index = 0; 01124 FOREACHC(it, listGeomProperties) { 01125 vertices[index].resize(it->vertices.size()); 01126 for(size_t i = 0; i < it->vertices.size(); ++i) { 01127 vertices[index][i] = _poseMult(it->_t, it->vertices[i]); 01128 } 01129 indices[index].resize(it->indices.size()); 01130 for(size_t i = 0; i < it->indices.size(); ++i) { 01131 indices[index][i] = it->indices[i]; 01132 } 01133 ambients[index] = it->ambientColor; 01134 diffuses[index] = it->diffuseColor; 01135 // workaround for mesh_loader.cpp:421 01136 // Most of are DAE files don't have ambient color defined 01137 ambients[index].r *= 0.5; ambients[index].g *= 0.5; ambients[index].b *= 0.5; 01138 if ( ambients[index].r == 0.0 ) { 01139 ambients[index].r = 0.0001; 01140 } 01141 if ( ambients[index].g == 0.0 ) { 01142 ambients[index].g = 0.0001; 01143 } 01144 if ( ambients[index].b == 0.0 ) { 01145 ambients[index].b = 0.0001; 01146 } 01147 index++; 01148 } 01149 01150 // have to save the geometry into individual collada 1.4 files since URDF does not allow triangle meshes to be specified 01151 std::stringstream daedata; 01152 daedata << str(boost::format("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\ 01153 <COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">\n\ 01154 <asset>\n\ 01155 <contributor>\n\ 01156 <author>Rosen Diankov</author>\n\ 01157 <comments>\n\ 01158 robot_model/urdf temporary collada geometry\n\ 01159 </comments>\n\ 01160 </contributor>\n\ 01161 <unit name=\"meter\" meter=\"1.0\"/>\n\ 01162 <up_axis>Z_UP</up_axis>\n\ 01163 </asset>\n\ 01164 <library_materials>\n")); 01165 for(unsigned int i=0; i < index; i++) { 01166 daedata << str(boost::format("\ 01167 <material id=\"blinn2%d\" name=\"blinn2%d\">\n\ 01168 <instance_effect url=\"#blinn2-fx%d\"/>\n\ 01169 </material>\n")%i%i%i); 01170 } 01171 daedata << "\ 01172 </library_materials>\n\ 01173 <library_effects>\n"; 01174 for(unsigned int i=0; i < index; i++) { 01175 daedata << str(boost::format("\ 01176 <effect id=\"blinn2-fx%d\">\n\ 01177 <profile_COMMON>\n\ 01178 <technique sid=\"common\">\n\ 01179 <phong>\n\ 01180 <ambient>\n\ 01181 <color>%f %f %f %f</color>\n\ 01182 </ambient>\n\ 01183 <diffuse>\n\ 01184 <color>%f %f %f %f</color>\n\ 01185 </diffuse>\n\ 01186 <specular>\n\ 01187 <color>0 0 0 1</color>\n\ 01188 </specular>\n\ 01189 </phong>\n\ 01190 </technique>\n\ 01191 </profile_COMMON>\n\ 01192 </effect>\n")%i%ambients[i].r%ambients[i].g%ambients[i].b%ambients[i].a%diffuses[i].r%diffuses[i].g%diffuses[i].b%diffuses[i].a); 01193 } 01194 daedata << str(boost::format("\ 01195 </library_effects>\n\ 01196 <library_geometries>\n")); 01197 // fill with vertices 01198 for(unsigned int i=0; i < index; i++) { 01199 daedata << str(boost::format("\ 01200 <geometry id=\"base2_M1KShape%d\" name=\"base2_M1KShape%d\">\n\ 01201 <mesh>\n\ 01202 <source id=\"geo0.positions\">\n\ 01203 <float_array id=\"geo0.positions-array\" count=\"%d\">")%i%i%(vertices[i].size()*3)); 01204 FOREACH(it,vertices[i]) { 01205 daedata << it->x << " " << it->y << " " << it->z << " "; 01206 } 01207 daedata << str(boost::format("\n\ 01208 </float_array>\n\ 01209 <technique_common>\n\ 01210 <accessor count=\"%d\" source=\"#geo0.positions-array\" stride=\"3\">\n\ 01211 <param name=\"X\" type=\"float\"/>\n\ 01212 <param name=\"Y\" type=\"float\"/>\n\ 01213 <param name=\"Z\" type=\"float\"/>\n\ 01214 </accessor>\n\ 01215 </technique_common>\n\ 01216 </source>\n\ 01217 <vertices id=\"geo0.vertices\">\n\ 01218 <input semantic=\"POSITION\" source=\"#geo0.positions\"/>\n\ 01219 </vertices>\n\ 01220 <triangles count=\"%d\" material=\"lambert2SG\">\n\ 01221 <input offset=\"0\" semantic=\"VERTEX\" source=\"#geo0.vertices\"/>\n\ 01222 <p>")%vertices[i].size()%(indices[i].size()/3)); 01223 // fill with indices 01224 FOREACH(it,indices[i]) { 01225 daedata << *it << " "; 01226 } 01227 daedata << str(boost::format("</p>\n\ 01228 </triangles>\n\ 01229 </mesh>\n\ 01230 </geometry>\n")); 01231 } 01232 daedata << str(boost::format("\ 01233 </library_geometries>\n\ 01234 <library_visual_scenes>\n\ 01235 <visual_scene id=\"VisualSceneNode\" name=\"base1d_med\">\n\ 01236 <node id=\"%s\" name=\"%s\" type=\"NODE\">\n")%name%name); 01237 for(unsigned int i=0; i < index; i++) { 01238 daedata << str(boost::format("\ 01239 <instance_geometry url=\"#base2_M1KShape%i\">\n\ 01240 <bind_material>\n\ 01241 <technique_common>\n\ 01242 <instance_material symbol=\"lambert2SG\" target=\"#blinn2%i\"/>\n\ 01243 </technique_common>\n\ 01244 </bind_material>\n\ 01245 </instance_geometry>\n")%i%i); 01246 } 01247 daedata << str(boost::format("\ 01248 </node>\n\ 01249 </visual_scene>\n\ 01250 </library_visual_scenes>\n\ 01251 <scene>\n\ 01252 <instance_visual_scene url=\"#VisualSceneNode\"/>\n\ 01253 </scene>\n\ 01254 </COLLADA>")); 01255 01256 #ifdef HAVE_MKSTEMPS 01257 geometry->filename = str(boost::format("/tmp/collada_model_reader_%s_XXXXXX.dae")%name); 01258 int fd = mkstemps(&geometry->filename[0],4); 01259 #else 01260 int fd = -1; 01261 for(int iter = 0; iter < 1000; ++iter) { 01262 geometry->filename = str(boost::format("/tmp/collada_model_reader_%s_%d.dae")%name%rand()); 01263 if( !!std::ifstream(geometry->filename.c_str())) { 01264 fd = open(geometry->filename.c_str(),O_WRONLY|O_CREAT|O_EXCL); 01265 if( fd != -1 ) { 01266 break; 01267 } 01268 } 01269 } 01270 if( fd == -1 ) { 01271 ROS_ERROR("failed to open geometry dae file %s",geometry->filename.c_str()); 01272 return geometry; 01273 } 01274 #endif 01275 //ROS_INFO("temp file: %s",geometry->filename.c_str()); 01276 std::string daedatastr = daedata.str(); 01277 if( (size_t)write(fd,daedatastr.c_str(),daedatastr.size()) != daedatastr.size() ) { 01278 ROS_ERROR("failed to write to geometry dae file %s",geometry->filename.c_str()); 01279 } 01280 close(fd); 01281 _listTempFilenames.push_back(boost::shared_ptr<UnlinkFilename>(new UnlinkFilename(geometry->filename))); 01282 geometry->filename = std::string("file://") + geometry->filename; 01283 return geometry; 01284 } 01285 01289 void _ExtractGeometry(const domNodeRef pdomnode,std::list<GEOMPROPERTIES>& listGeomProperties, const std::list<JointAxisBinding>& listAxisBindings, const Pose& tlink) 01290 { 01291 if( !pdomnode ) { 01292 return; 01293 } 01294 01295 ROS_DEBUG_STREAM(str(boost::format("ExtractGeometry(node,link) of %s\n")%pdomnode->getName())); 01296 01297 // For all child nodes of pdomnode 01298 for (size_t i = 0; i < pdomnode->getNode_array().getCount(); i++) { 01299 // check if contains a joint 01300 bool contains=false; 01301 FOREACHC(it,listAxisBindings) { 01302 // don't check ID's check if the reference is the same! 01303 if ( (pdomnode->getNode_array()[i]) == (it->visualnode)) { 01304 contains=true; 01305 break; 01306 } 01307 } 01308 if (contains) { 01309 continue; 01310 } 01311 01312 _ExtractGeometry(pdomnode->getNode_array()[i],listGeomProperties, listAxisBindings,tlink); 01313 // Plink stayes the same for all children 01314 // replace pdomnode by child = pdomnode->getNode_array()[i] 01315 // hope for the best! 01316 // put everything in a subroutine in order to process pdomnode too! 01317 } 01318 01319 unsigned int nGeomBefore = listGeomProperties.size(); // #of Meshes already associated to this link 01320 01321 // get the geometry 01322 for (size_t igeom = 0; igeom < pdomnode->getInstance_geometry_array().getCount(); ++igeom) { 01323 domInstance_geometryRef domigeom = pdomnode->getInstance_geometry_array()[igeom]; 01324 domGeometryRef domgeom = daeSafeCast<domGeometry> (domigeom->getUrl().getElement()); 01325 if (!domgeom) { 01326 continue; 01327 } 01328 01329 // Gets materials 01330 std::map<std::string, domMaterialRef> mapmaterials; 01331 if (!!domigeom->getBind_material() && !!domigeom->getBind_material()->getTechnique_common()) { 01332 const domInstance_material_Array& matarray = domigeom->getBind_material()->getTechnique_common()->getInstance_material_array(); 01333 for (size_t imat = 0; imat < matarray.getCount(); ++imat) { 01334 domMaterialRef pmat = daeSafeCast<domMaterial>(matarray[imat]->getTarget().getElement()); 01335 if (!!pmat) { 01336 mapmaterials[matarray[imat]->getSymbol()] = pmat; 01337 } 01338 } 01339 } 01340 01341 // Gets the geometry 01342 _ExtractGeometry(domgeom, mapmaterials, listGeomProperties); 01343 } 01344 01345 std::list<GEOMPROPERTIES>::iterator itgeom= listGeomProperties.begin(); 01346 for (unsigned int i=0; i< nGeomBefore; i++) { 01347 itgeom++; // change only the transformations of the newly found geometries. 01348 } 01349 01350 boost::array<double,12> tmnodegeom = _poseMult(_matrixFromPose(_poseInverse(tlink)), _poseMult(_getNodeParentTransform(pdomnode), _ExtractFullTransform(pdomnode))); 01351 Pose tnodegeom; 01352 Vector3 vscale(1,1,1); 01353 _decompose(tmnodegeom, tnodegeom, vscale); 01354 01355 // std::stringstream ss; ss << "geom: "; 01356 // for(int i = 0; i < 4; ++i) { 01357 // ss << tmnodegeom[4*0+i] << " " << tmnodegeom[4*1+i] << " " << tmnodegeom[4*2+i] << " "; 01358 // } 01359 // ROS_INFO(ss.str().c_str()); 01360 01361 // Switch between different type of geometry PRIMITIVES 01362 for (; itgeom != listGeomProperties.end(); itgeom++) { 01363 itgeom->_t = tnodegeom; 01364 switch (itgeom->type) { 01365 case GeomBox: 01366 itgeom->vGeomData.x *= vscale.x; 01367 itgeom->vGeomData.y *= vscale.y; 01368 itgeom->vGeomData.z *= vscale.z; 01369 break; 01370 case GeomSphere: { 01371 itgeom->vGeomData.x *= std::max(vscale.z, std::max(vscale.x, vscale.y)); 01372 break; 01373 } 01374 case GeomCylinder: 01375 itgeom->vGeomData.x *= std::max(vscale.x, vscale.y); 01376 itgeom->vGeomData.y *= vscale.z; 01377 break; 01378 case GeomTrimesh: 01379 for(size_t i = 0; i < itgeom->vertices.size(); ++i ) { 01380 itgeom->vertices[i] = _poseMult(tmnodegeom,itgeom->vertices[i]); 01381 } 01382 itgeom->_t = Pose(); // reset back to identity 01383 break; 01384 default: 01385 ROS_WARN_STREAM(str(boost::format("unknown geometry type: %d\n")%itgeom->type)); 01386 } 01387 } 01388 } 01389 01393 void _FillGeometryColor(const domMaterialRef pmat, GEOMPROPERTIES& geom) 01394 { 01395 if( !!pmat && !!pmat->getInstance_effect() ) { 01396 domEffectRef peffect = daeSafeCast<domEffect>(pmat->getInstance_effect()->getUrl().getElement().cast()); 01397 if( !!peffect ) { 01398 domProfile_common::domTechnique::domPhongRef pphong = daeSafeCast<domProfile_common::domTechnique::domPhong>(peffect->getDescendant(daeElement::matchType(domProfile_common::domTechnique::domPhong::ID()))); 01399 if( !!pphong ) { 01400 if( !!pphong->getAmbient() && !!pphong->getAmbient()->getColor() ) { 01401 domFx_color c = pphong->getAmbient()->getColor()->getValue(); 01402 geom.ambientColor.r = c[0]; 01403 geom.ambientColor.g = c[1]; 01404 geom.ambientColor.b = c[2]; 01405 geom.ambientColor.a = c[3]; 01406 } 01407 if( !!pphong->getDiffuse() && !!pphong->getDiffuse()->getColor() ) { 01408 domFx_color c = pphong->getDiffuse()->getColor()->getValue(); 01409 geom.diffuseColor.r = c[0]; 01410 geom.diffuseColor.g = c[1]; 01411 geom.diffuseColor.b = c[2]; 01412 geom.diffuseColor.a = c[3]; 01413 } 01414 } 01415 } 01416 } 01417 } 01418 01424 bool _ExtractGeometry(const domTrianglesRef triRef, const domVerticesRef vertsRef, const std::map<std::string,domMaterialRef>& mapmaterials, std::list<GEOMPROPERTIES>& listGeomProperties) 01425 { 01426 if( !triRef ) { 01427 return false; 01428 } 01429 listGeomProperties.push_back(GEOMPROPERTIES()); 01430 GEOMPROPERTIES& geom = listGeomProperties.back(); 01431 geom.type = GeomTrimesh; 01432 01433 // resolve the material and assign correct colors to the geometry 01434 if( !!triRef->getMaterial() ) { 01435 std::map<std::string,domMaterialRef>::const_iterator itmat = mapmaterials.find(triRef->getMaterial()); 01436 if( itmat != mapmaterials.end() ) { 01437 _FillGeometryColor(itmat->second,geom); 01438 } 01439 } 01440 01441 size_t triangleIndexStride = 0, vertexoffset = -1; 01442 domInput_local_offsetRef indexOffsetRef; 01443 01444 for (unsigned int w=0; w<triRef->getInput_array().getCount(); w++) { 01445 size_t offset = triRef->getInput_array()[w]->getOffset(); 01446 daeString str = triRef->getInput_array()[w]->getSemantic(); 01447 if (!strcmp(str,"VERTEX")) { 01448 indexOffsetRef = triRef->getInput_array()[w]; 01449 vertexoffset = offset; 01450 } 01451 if (offset> triangleIndexStride) { 01452 triangleIndexStride = offset; 01453 } 01454 } 01455 triangleIndexStride++; 01456 01457 const domList_of_uints& indexArray =triRef->getP()->getValue(); 01458 geom.indices.reserve(triRef->getCount()*3); 01459 geom.vertices.reserve(triRef->getCount()*3); 01460 for (size_t i=0; i<vertsRef->getInput_array().getCount(); ++i) { 01461 domInput_localRef localRef = vertsRef->getInput_array()[i]; 01462 daeString str = localRef->getSemantic(); 01463 if ( strcmp(str,"POSITION") == 0 ) { 01464 const domSourceRef node = daeSafeCast<domSource>(localRef->getSource().getElement()); 01465 if( !node ) { 01466 continue; 01467 } 01468 double fUnitScale = _GetUnitScale(node); 01469 const domFloat_arrayRef flArray = node->getFloat_array(); 01470 if (!!flArray) { 01471 const domList_of_floats& listFloats = flArray->getValue(); 01472 int k=vertexoffset; 01473 int vertexStride = 3; //instead of hardcoded stride, should use the 'accessor' 01474 for(size_t itri = 0; itri < triRef->getCount(); ++itri) { 01475 if(k+2*triangleIndexStride < indexArray.getCount() ) { 01476 for (int j=0; j<3; j++) { 01477 int index0 = indexArray.get(k)*vertexStride; 01478 domFloat fl0 = listFloats.get(index0); 01479 domFloat fl1 = listFloats.get(index0+1); 01480 domFloat fl2 = listFloats.get(index0+2); 01481 k+=triangleIndexStride; 01482 geom.indices.push_back(geom.vertices.size()); 01483 geom.vertices.push_back(Vector3(fl0*fUnitScale,fl1*fUnitScale,fl2*fUnitScale)); 01484 } 01485 } 01486 } 01487 } 01488 else { 01489 ROS_WARN_STREAM("float array not defined!\n"); 01490 } 01491 break; 01492 } 01493 } 01494 if( geom.indices.size() != 3*triRef->getCount() ) { 01495 ROS_WARN_STREAM("triangles declares wrong count!\n"); 01496 } 01497 geom.InitCollisionMesh(); 01498 return true; 01499 } 01500 01505 bool _ExtractGeometry(const domTrifansRef triRef, const domVerticesRef vertsRef, const std::map<std::string,domMaterialRef>& mapmaterials, std::list<GEOMPROPERTIES>& listGeomProperties) 01506 { 01507 if( !triRef ) { 01508 return false; 01509 } 01510 listGeomProperties.push_back(GEOMPROPERTIES()); 01511 GEOMPROPERTIES& geom = listGeomProperties.back(); 01512 geom.type = GeomTrimesh; 01513 01514 // resolve the material and assign correct colors to the geometry 01515 if( !!triRef->getMaterial() ) { 01516 std::map<std::string,domMaterialRef>::const_iterator itmat = mapmaterials.find(triRef->getMaterial()); 01517 if( itmat != mapmaterials.end() ) { 01518 _FillGeometryColor(itmat->second,geom); 01519 } 01520 } 01521 01522 size_t triangleIndexStride = 0, vertexoffset = -1; 01523 domInput_local_offsetRef indexOffsetRef; 01524 01525 for (unsigned int w=0; w<triRef->getInput_array().getCount(); w++) { 01526 size_t offset = triRef->getInput_array()[w]->getOffset(); 01527 daeString str = triRef->getInput_array()[w]->getSemantic(); 01528 if (!strcmp(str,"VERTEX")) { 01529 indexOffsetRef = triRef->getInput_array()[w]; 01530 vertexoffset = offset; 01531 } 01532 if (offset> triangleIndexStride) { 01533 triangleIndexStride = offset; 01534 } 01535 } 01536 triangleIndexStride++; 01537 size_t primitivecount = triRef->getCount(); 01538 if( primitivecount > triRef->getP_array().getCount() ) { 01539 ROS_WARN_STREAM("trifans has incorrect count\n"); 01540 primitivecount = triRef->getP_array().getCount(); 01541 } 01542 for(size_t ip = 0; ip < primitivecount; ++ip) { 01543 domList_of_uints indexArray =triRef->getP_array()[ip]->getValue(); 01544 for (size_t i=0; i<vertsRef->getInput_array().getCount(); ++i) { 01545 domInput_localRef localRef = vertsRef->getInput_array()[i]; 01546 daeString str = localRef->getSemantic(); 01547 if ( strcmp(str,"POSITION") == 0 ) { 01548 const domSourceRef node = daeSafeCast<domSource>(localRef->getSource().getElement()); 01549 if( !node ) { 01550 continue; 01551 } 01552 double fUnitScale = _GetUnitScale(node); 01553 const domFloat_arrayRef flArray = node->getFloat_array(); 01554 if (!!flArray) { 01555 const domList_of_floats& listFloats = flArray->getValue(); 01556 int k=vertexoffset; 01557 int vertexStride = 3; //instead of hardcoded stride, should use the 'accessor' 01558 size_t usedindices = 3*(indexArray.getCount()-2); 01559 if( geom.indices.capacity() < geom.indices.size()+usedindices ) { 01560 geom.indices.reserve(geom.indices.size()+usedindices); 01561 } 01562 if( geom.vertices.capacity() < geom.vertices.size()+indexArray.getCount() ) { 01563 geom.vertices.reserve(geom.vertices.size()+indexArray.getCount()); 01564 } 01565 size_t startoffset = (int)geom.vertices.size(); 01566 while(k < (int)indexArray.getCount() ) { 01567 int index0 = indexArray.get(k)*vertexStride; 01568 domFloat fl0 = listFloats.get(index0); 01569 domFloat fl1 = listFloats.get(index0+1); 01570 domFloat fl2 = listFloats.get(index0+2); 01571 k+=triangleIndexStride; 01572 geom.vertices.push_back(Vector3(fl0*fUnitScale,fl1*fUnitScale,fl2*fUnitScale)); 01573 } 01574 for(size_t ivert = startoffset+2; ivert < geom.vertices.size(); ++ivert) { 01575 geom.indices.push_back(startoffset); 01576 geom.indices.push_back(ivert-1); 01577 geom.indices.push_back(ivert); 01578 } 01579 } 01580 else { 01581 ROS_WARN_STREAM("float array not defined!\n"); 01582 } 01583 break; 01584 } 01585 } 01586 } 01587 01588 geom.InitCollisionMesh(); 01589 return false; 01590 } 01591 01596 bool _ExtractGeometry(const domTristripsRef triRef, const domVerticesRef vertsRef, const std::map<std::string,domMaterialRef>& mapmaterials, std::list<GEOMPROPERTIES>& listGeomProperties) 01597 { 01598 if( !triRef ) { 01599 return false; 01600 } 01601 listGeomProperties.push_back(GEOMPROPERTIES()); 01602 GEOMPROPERTIES& geom = listGeomProperties.back(); 01603 geom.type = GeomTrimesh; 01604 01605 // resolve the material and assign correct colors to the geometry 01606 if( !!triRef->getMaterial() ) { 01607 std::map<std::string,domMaterialRef>::const_iterator itmat = mapmaterials.find(triRef->getMaterial()); 01608 if( itmat != mapmaterials.end() ) { 01609 _FillGeometryColor(itmat->second,geom); 01610 } 01611 } 01612 size_t triangleIndexStride = 0, vertexoffset = -1; 01613 domInput_local_offsetRef indexOffsetRef; 01614 01615 for (unsigned int w=0; w<triRef->getInput_array().getCount(); w++) { 01616 size_t offset = triRef->getInput_array()[w]->getOffset(); 01617 daeString str = triRef->getInput_array()[w]->getSemantic(); 01618 if (!strcmp(str,"VERTEX")) { 01619 indexOffsetRef = triRef->getInput_array()[w]; 01620 vertexoffset = offset; 01621 } 01622 if (offset> triangleIndexStride) { 01623 triangleIndexStride = offset; 01624 } 01625 } 01626 triangleIndexStride++; 01627 size_t primitivecount = triRef->getCount(); 01628 if( primitivecount > triRef->getP_array().getCount() ) { 01629 ROS_WARN_STREAM("tristrips has incorrect count\n"); 01630 primitivecount = triRef->getP_array().getCount(); 01631 } 01632 for(size_t ip = 0; ip < primitivecount; ++ip) { 01633 domList_of_uints indexArray = triRef->getP_array()[ip]->getValue(); 01634 for (size_t i=0; i<vertsRef->getInput_array().getCount(); ++i) { 01635 domInput_localRef localRef = vertsRef->getInput_array()[i]; 01636 daeString str = localRef->getSemantic(); 01637 if ( strcmp(str,"POSITION") == 0 ) { 01638 const domSourceRef node = daeSafeCast<domSource>(localRef->getSource().getElement()); 01639 if( !node ) { 01640 continue; 01641 } 01642 double fUnitScale = _GetUnitScale(node); 01643 const domFloat_arrayRef flArray = node->getFloat_array(); 01644 if (!!flArray) { 01645 const domList_of_floats& listFloats = flArray->getValue(); 01646 int k=vertexoffset; 01647 int vertexStride = 3; //instead of hardcoded stride, should use the 'accessor' 01648 size_t usedindices = indexArray.getCount()-2; 01649 if( geom.indices.capacity() < geom.indices.size()+usedindices ) { 01650 geom.indices.reserve(geom.indices.size()+usedindices); 01651 } 01652 if( geom.vertices.capacity() < geom.vertices.size()+indexArray.getCount() ) { 01653 geom.vertices.reserve(geom.vertices.size()+indexArray.getCount()); 01654 } 01655 01656 size_t startoffset = (int)geom.vertices.size(); 01657 while(k < (int)indexArray.getCount() ) { 01658 int index0 = indexArray.get(k)*vertexStride; 01659 domFloat fl0 = listFloats.get(index0); 01660 domFloat fl1 = listFloats.get(index0+1); 01661 domFloat fl2 = listFloats.get(index0+2); 01662 k+=triangleIndexStride; 01663 geom.vertices.push_back(Vector3(fl0*fUnitScale,fl1*fUnitScale,fl2*fUnitScale)); 01664 } 01665 01666 bool bFlip = false; 01667 for(size_t ivert = startoffset+2; ivert < geom.vertices.size(); ++ivert) { 01668 geom.indices.push_back(ivert-2); 01669 geom.indices.push_back(bFlip ? ivert : ivert-1); 01670 geom.indices.push_back(bFlip ? ivert-1 : ivert); 01671 bFlip = !bFlip; 01672 } 01673 } 01674 else { 01675 ROS_WARN_STREAM("float array not defined!\n"); 01676 } 01677 break; 01678 } 01679 } 01680 } 01681 01682 geom.InitCollisionMesh(); 01683 return false; 01684 } 01685 01690 bool _ExtractGeometry(const domPolylistRef triRef, const domVerticesRef vertsRef, const std::map<std::string,domMaterialRef>& mapmaterials, std::list<GEOMPROPERTIES>& listGeomProperties) 01691 { 01692 if( !triRef ) { 01693 return false; 01694 } 01695 listGeomProperties.push_back(GEOMPROPERTIES()); 01696 GEOMPROPERTIES& geom = listGeomProperties.back(); 01697 geom.type = GeomTrimesh; 01698 01699 // resolve the material and assign correct colors to the geometry 01700 if( !!triRef->getMaterial() ) { 01701 std::map<std::string,domMaterialRef>::const_iterator itmat = mapmaterials.find(triRef->getMaterial()); 01702 if( itmat != mapmaterials.end() ) { 01703 _FillGeometryColor(itmat->second,geom); 01704 } 01705 } 01706 01707 size_t triangleIndexStride = 0,vertexoffset = -1; 01708 domInput_local_offsetRef indexOffsetRef; 01709 for (unsigned int w=0; w<triRef->getInput_array().getCount(); w++) { 01710 size_t offset = triRef->getInput_array()[w]->getOffset(); 01711 daeString str = triRef->getInput_array()[w]->getSemantic(); 01712 if (!strcmp(str,"VERTEX")) { 01713 indexOffsetRef = triRef->getInput_array()[w]; 01714 vertexoffset = offset; 01715 } 01716 if (offset> triangleIndexStride) { 01717 triangleIndexStride = offset; 01718 } 01719 } 01720 triangleIndexStride++; 01721 const domList_of_uints& indexArray =triRef->getP()->getValue(); 01722 for (size_t i=0; i<vertsRef->getInput_array().getCount(); ++i) { 01723 domInput_localRef localRef = vertsRef->getInput_array()[i]; 01724 daeString str = localRef->getSemantic(); 01725 if ( strcmp(str,"POSITION") == 0 ) { 01726 const domSourceRef node = daeSafeCast<domSource>(localRef->getSource().getElement()); 01727 if( !node ) { 01728 continue; 01729 } 01730 double fUnitScale = _GetUnitScale(node); 01731 const domFloat_arrayRef flArray = node->getFloat_array(); 01732 if (!!flArray) { 01733 const domList_of_floats& listFloats = flArray->getValue(); 01734 size_t k=vertexoffset; 01735 int vertexStride = 3; //instead of hardcoded stride, should use the 'accessor' 01736 for(size_t ipoly = 0; ipoly < triRef->getVcount()->getValue().getCount(); ++ipoly) { 01737 size_t numverts = triRef->getVcount()->getValue()[ipoly]; 01738 if(numverts > 0 && k+(numverts-1)*triangleIndexStride < indexArray.getCount() ) { 01739 size_t startoffset = geom.vertices.size(); 01740 for (size_t j=0; j<numverts; j++) { 01741 int index0 = indexArray.get(k)*vertexStride; 01742 domFloat fl0 = listFloats.get(index0); 01743 domFloat fl1 = listFloats.get(index0+1); 01744 domFloat fl2 = listFloats.get(index0+2); 01745 k+=triangleIndexStride; 01746 geom.vertices.push_back(Vector3(fl0*fUnitScale,fl1*fUnitScale,fl2*fUnitScale)); 01747 } 01748 for(size_t ivert = startoffset+2; ivert < geom.vertices.size(); ++ivert) { 01749 geom.indices.push_back(startoffset); 01750 geom.indices.push_back(ivert-1); 01751 geom.indices.push_back(ivert); 01752 } 01753 } 01754 } 01755 } 01756 else { 01757 ROS_WARN_STREAM("float array not defined!\n"); 01758 } 01759 break; 01760 } 01761 } 01762 geom.InitCollisionMesh(); 01763 return false; 01764 } 01765 01769 bool _ExtractGeometry(const domGeometryRef geom, const std::map<std::string,domMaterialRef>& mapmaterials, std::list<GEOMPROPERTIES>& listGeomProperties) 01770 { 01771 if( !geom ) { 01772 return false; 01773 } 01774 std::vector<Vector3> vconvexhull; 01775 if (geom->getMesh()) { 01776 const domMeshRef meshRef = geom->getMesh(); 01777 for (size_t tg = 0; tg<meshRef->getTriangles_array().getCount(); tg++) { 01778 _ExtractGeometry(meshRef->getTriangles_array()[tg], meshRef->getVertices(), mapmaterials, listGeomProperties); 01779 } 01780 for (size_t tg = 0; tg<meshRef->getTrifans_array().getCount(); tg++) { 01781 _ExtractGeometry(meshRef->getTrifans_array()[tg], meshRef->getVertices(), mapmaterials, listGeomProperties); 01782 } 01783 for (size_t tg = 0; tg<meshRef->getTristrips_array().getCount(); tg++) { 01784 _ExtractGeometry(meshRef->getTristrips_array()[tg], meshRef->getVertices(), mapmaterials, listGeomProperties); 01785 } 01786 for (size_t tg = 0; tg<meshRef->getPolylist_array().getCount(); tg++) { 01787 _ExtractGeometry(meshRef->getPolylist_array()[tg], meshRef->getVertices(), mapmaterials, listGeomProperties); 01788 } 01789 if( meshRef->getPolygons_array().getCount()> 0 ) { 01790 ROS_WARN_STREAM("openrave does not support collada polygons\n"); 01791 } 01792 01793 // if( alltrimesh.vertices.size() == 0 ) { 01794 // const domVerticesRef vertsRef = meshRef->getVertices(); 01795 // for (size_t i=0;i<vertsRef->getInput_array().getCount();i++) { 01796 // domInput_localRef localRef = vertsRef->getInput_array()[i]; 01797 // daeString str = localRef->getSemantic(); 01798 // if ( strcmp(str,"POSITION") == 0 ) { 01799 // const domSourceRef node = daeSafeCast<domSource>(localRef->getSource().getElement()); 01800 // if( !node ) 01801 // continue; 01802 // double fUnitScale = _GetUnitScale(node); 01803 // const domFloat_arrayRef flArray = node->getFloat_array(); 01804 // if (!!flArray) { 01805 // const domList_of_floats& listFloats = flArray->getValue(); 01806 // int vertexStride = 3;//instead of hardcoded stride, should use the 'accessor' 01807 // vconvexhull.reserve(vconvexhull.size()+listFloats.getCount()); 01808 // for (size_t vertIndex = 0;vertIndex < listFloats.getCount();vertIndex+=vertexStride) { 01809 // //btVector3 verts[3]; 01810 // domFloat fl0 = listFloats.get(vertIndex); 01811 // domFloat fl1 = listFloats.get(vertIndex+1); 01812 // domFloat fl2 = listFloats.get(vertIndex+2); 01813 // vconvexhull.push_back(Vector3(fl0*fUnitScale,fl1*fUnitScale,fl2*fUnitScale)); 01814 // } 01815 // } 01816 // } 01817 // } 01818 // 01819 // _computeConvexHull(vconvexhull,alltrimesh); 01820 // } 01821 01822 return true; 01823 } 01824 else if (geom->getConvex_mesh()) { 01825 { 01826 const domConvex_meshRef convexRef = geom->getConvex_mesh(); 01827 daeElementRef otherElemRef = convexRef->getConvex_hull_of().getElement(); 01828 if ( !!otherElemRef ) { 01829 domGeometryRef linkedGeom = *(domGeometryRef*)&otherElemRef; 01830 ROS_WARN_STREAM( "otherLinked\n"); 01831 } 01832 else { 01833 ROS_WARN("convexMesh polyCount = %d\n",(int)convexRef->getPolygons_array().getCount()); 01834 ROS_WARN("convexMesh triCount = %d\n",(int)convexRef->getTriangles_array().getCount()); 01835 } 01836 } 01837 01838 const domConvex_meshRef convexRef = geom->getConvex_mesh(); 01839 //daeString urlref = convexRef->getConvex_hull_of().getURI(); 01840 daeString urlref2 = convexRef->getConvex_hull_of().getOriginalURI(); 01841 if (urlref2) { 01842 daeElementRef otherElemRef = convexRef->getConvex_hull_of().getElement(); 01843 01844 // Load all the geometry libraries 01845 for ( size_t i = 0; i < _dom->getLibrary_geometries_array().getCount(); i++) { 01846 domLibrary_geometriesRef libgeom = _dom->getLibrary_geometries_array()[i]; 01847 for (size_t i = 0; i < libgeom->getGeometry_array().getCount(); i++) { 01848 domGeometryRef lib = libgeom->getGeometry_array()[i]; 01849 if (!strcmp(lib->getId(),urlref2+1)) { // skip the # at the front of urlref2 01850 //found convex_hull geometry 01851 domMesh *meshElement = lib->getMesh(); //linkedGeom->getMesh(); 01852 if (meshElement) { 01853 const domVerticesRef vertsRef = meshElement->getVertices(); 01854 for (size_t i=0; i<vertsRef->getInput_array().getCount(); i++) { 01855 domInput_localRef localRef = vertsRef->getInput_array()[i]; 01856 daeString str = localRef->getSemantic(); 01857 if ( strcmp(str,"POSITION") == 0) { 01858 const domSourceRef node = daeSafeCast<domSource>(localRef->getSource().getElement()); 01859 if( !node ) { 01860 continue; 01861 } 01862 double fUnitScale = _GetUnitScale(node); 01863 const domFloat_arrayRef flArray = node->getFloat_array(); 01864 if (!!flArray) { 01865 vconvexhull.reserve(vconvexhull.size()+flArray->getCount()); 01866 const domList_of_floats& listFloats = flArray->getValue(); 01867 for (size_t k=0; k+2<flArray->getCount(); k+=3) { 01868 domFloat fl0 = listFloats.get(k); 01869 domFloat fl1 = listFloats.get(k+1); 01870 domFloat fl2 = listFloats.get(k+2); 01871 vconvexhull.push_back(Vector3(fl0*fUnitScale,fl1*fUnitScale,fl2*fUnitScale)); 01872 } 01873 } 01874 } 01875 } 01876 } 01877 } 01878 } 01879 } 01880 } 01881 else { 01882 //no getConvex_hull_of but direct vertices 01883 const domVerticesRef vertsRef = convexRef->getVertices(); 01884 for (size_t i=0; i<vertsRef->getInput_array().getCount(); i++) { 01885 domInput_localRef localRef = vertsRef->getInput_array()[i]; 01886 daeString str = localRef->getSemantic(); 01887 if ( strcmp(str,"POSITION") == 0 ) { 01888 const domSourceRef node = daeSafeCast<domSource>(localRef->getSource().getElement()); 01889 if( !node ) { 01890 continue; 01891 } 01892 double fUnitScale = _GetUnitScale(node); 01893 const domFloat_arrayRef flArray = node->getFloat_array(); 01894 if (!!flArray) { 01895 const domList_of_floats& listFloats = flArray->getValue(); 01896 vconvexhull.reserve(vconvexhull.size()+flArray->getCount()); 01897 for (size_t k=0; k+2<flArray->getCount(); k+=3) { 01898 domFloat fl0 = listFloats.get(k); 01899 domFloat fl1 = listFloats.get(k+1); 01900 domFloat fl2 = listFloats.get(k+2); 01901 vconvexhull.push_back(Vector3(fl0*fUnitScale,fl1*fUnitScale,fl2*fUnitScale)); 01902 } 01903 } 01904 } 01905 } 01906 } 01907 01908 if( vconvexhull.size()> 0 ) { 01909 listGeomProperties.push_back(GEOMPROPERTIES()); 01910 GEOMPROPERTIES& geom = listGeomProperties.back(); 01911 geom.type = GeomTrimesh; 01912 01913 //_computeConvexHull(vconvexhull,trimesh); 01914 geom.InitCollisionMesh(); 01915 } 01916 return true; 01917 } 01918 01919 return false; 01920 } 01921 01923 void _ExtractRobotManipulators(const domArticulated_systemRef as) 01924 { 01925 ROS_DEBUG("collada manipulators not supported yet"); 01926 } 01927 01929 void _ExtractRobotAttachedSensors(const domArticulated_systemRef as) 01930 { 01931 ROS_DEBUG("collada sensors not supported yet"); 01932 } 01933 01934 inline daeElementRef _getElementFromUrl(const daeURI &uri) 01935 { 01936 return daeStandardURIResolver(*_collada).resolveElement(uri); 01937 } 01938 01939 static daeElement* searchBinding(domCommon_sidref_or_paramRef paddr, daeElementRef parent) 01940 { 01941 if( !!paddr->getSIDREF() ) { 01942 return daeSidRef(paddr->getSIDREF()->getValue(),parent).resolve().elt; 01943 } 01944 if (!!paddr->getParam()) { 01945 return searchBinding(paddr->getParam()->getValue(),parent); 01946 } 01947 return NULL; 01948 } 01949 01953 static daeElement* searchBinding(daeString ref, daeElementRef parent) 01954 { 01955 if( !parent ) { 01956 return NULL; 01957 } 01958 daeElement* pelt = NULL; 01959 domKinematics_sceneRef kscene = daeSafeCast<domKinematics_scene>(parent.cast()); 01960 if( !!kscene ) { 01961 pelt = searchBindingArray(ref,kscene->getInstance_articulated_system_array()); 01962 if( !!pelt ) { 01963 return pelt; 01964 } 01965 return searchBindingArray(ref,kscene->getInstance_kinematics_model_array()); 01966 } 01967 domArticulated_systemRef articulated_system = daeSafeCast<domArticulated_system>(parent.cast()); 01968 if( !!articulated_system ) { 01969 if( !!articulated_system->getKinematics() ) { 01970 pelt = searchBindingArray(ref,articulated_system->getKinematics()->getInstance_kinematics_model_array()); 01971 if( !!pelt ) { 01972 return pelt; 01973 } 01974 } 01975 if( !!articulated_system->getMotion() ) { 01976 return searchBinding(ref,articulated_system->getMotion()->getInstance_articulated_system()); 01977 } 01978 return NULL; 01979 } 01980 // try to get a bind array 01981 daeElementRef pbindelt; 01982 const domKinematics_bind_Array* pbindarray = NULL; 01983 const domKinematics_newparam_Array* pnewparamarray = NULL; 01984 domInstance_articulated_systemRef ias = daeSafeCast<domInstance_articulated_system>(parent.cast()); 01985 if( !!ias ) { 01986 pbindarray = &ias->getBind_array(); 01987 pbindelt = ias->getUrl().getElement(); 01988 pnewparamarray = &ias->getNewparam_array(); 01989 } 01990 if( !pbindarray || !pbindelt ) { 01991 domInstance_kinematics_modelRef ikm = daeSafeCast<domInstance_kinematics_model>(parent.cast()); 01992 if( !!ikm ) { 01993 pbindarray = &ikm->getBind_array(); 01994 pbindelt = ikm->getUrl().getElement(); 01995 pnewparamarray = &ikm->getNewparam_array(); 01996 } 01997 } 01998 if( !!pbindarray && !!pbindelt ) { 01999 for (size_t ibind = 0; ibind < pbindarray->getCount(); ++ibind) { 02000 domKinematics_bindRef pbind = (*pbindarray)[ibind]; 02001 if( !!pbind->getSymbol() && strcmp(pbind->getSymbol(), ref) == 0 ) { 02002 // found a match 02003 if( !!pbind->getParam() ) { 02004 return daeSidRef(pbind->getParam()->getRef(), pbindelt).resolve().elt; 02005 } 02006 else if( !!pbind->getSIDREF() ) { 02007 return daeSidRef(pbind->getSIDREF()->getValue(), pbindelt).resolve().elt; 02008 } 02009 } 02010 } 02011 for(size_t inewparam = 0; inewparam < pnewparamarray->getCount(); ++inewparam) { 02012 domKinematics_newparamRef newparam = (*pnewparamarray)[inewparam]; 02013 if( !!newparam->getSid() && strcmp(newparam->getSid(), ref) == 0 ) { 02014 if( !!newparam->getSIDREF() ) { // can only bind with SIDREF 02015 return daeSidRef(newparam->getSIDREF()->getValue(),pbindelt).resolve().elt; 02016 } 02017 ROS_WARN_STREAM(str(boost::format("newparam sid=%s does not have SIDREF\n")%newparam->getSid())); 02018 } 02019 } 02020 } 02021 ROS_WARN_STREAM(str(boost::format("failed to get binding '%s' for element: %s\n")%ref%parent->getElementName())); 02022 return NULL; 02023 } 02024 02025 static daeElement* searchBindingArray(daeString ref, const domInstance_articulated_system_Array& paramArray) 02026 { 02027 for(size_t iikm = 0; iikm < paramArray.getCount(); ++iikm) { 02028 daeElement* pelt = searchBinding(ref,paramArray[iikm].cast()); 02029 if( !!pelt ) { 02030 return pelt; 02031 } 02032 } 02033 return NULL; 02034 } 02035 02036 static daeElement* searchBindingArray(daeString ref, const domInstance_kinematics_model_Array& paramArray) 02037 { 02038 for(size_t iikm = 0; iikm < paramArray.getCount(); ++iikm) { 02039 daeElement* pelt = searchBinding(ref,paramArray[iikm].cast()); 02040 if( !!pelt ) { 02041 return pelt; 02042 } 02043 } 02044 return NULL; 02045 } 02046 02047 template <typename U> static xsBoolean resolveBool(domCommon_bool_or_paramRef paddr, const U& parent) { 02048 if( !!paddr->getBool() ) { 02049 return paddr->getBool()->getValue(); 02050 } 02051 if( !paddr->getParam() ) { 02052 ROS_WARN_STREAM("param not specified, setting to 0\n"); 02053 return false; 02054 } 02055 for(size_t iparam = 0; iparam < parent->getNewparam_array().getCount(); ++iparam) { 02056 domKinematics_newparamRef pnewparam = parent->getNewparam_array()[iparam]; 02057 if( !!pnewparam->getSid() && strcmp(pnewparam->getSid(), paddr->getParam()->getValue()) == 0 ) { 02058 if( !!pnewparam->getBool() ) { 02059 return pnewparam->getBool()->getValue(); 02060 } 02061 else if( !!pnewparam->getSIDREF() ) { 02062 domKinematics_newparam::domBoolRef ptarget = daeSafeCast<domKinematics_newparam::domBool>(daeSidRef(pnewparam->getSIDREF()->getValue(), pnewparam).resolve().elt); 02063 if( !ptarget ) { 02064 ROS_WARN("failed to resolve %s from %s\n", pnewparam->getSIDREF()->getValue(), paddr->getID()); 02065 continue; 02066 } 02067 return ptarget->getValue(); 02068 } 02069 } 02070 } 02071 ROS_WARN_STREAM(str(boost::format("failed to resolve %s\n")%paddr->getParam()->getValue())); 02072 return false; 02073 } 02074 template <typename U> static domFloat resolveFloat(domCommon_float_or_paramRef paddr, const U& parent) { 02075 if( !!paddr->getFloat() ) { 02076 return paddr->getFloat()->getValue(); 02077 } 02078 if( !paddr->getParam() ) { 02079 ROS_WARN_STREAM("param not specified, setting to 0\n"); 02080 return 0; 02081 } 02082 for(size_t iparam = 0; iparam < parent->getNewparam_array().getCount(); ++iparam) { 02083 domKinematics_newparamRef pnewparam = parent->getNewparam_array()[iparam]; 02084 if( !!pnewparam->getSid() && strcmp(pnewparam->getSid(), paddr->getParam()->getValue()) == 0 ) { 02085 if( !!pnewparam->getFloat() ) { 02086 return pnewparam->getFloat()->getValue(); 02087 } 02088 else if( !!pnewparam->getSIDREF() ) { 02089 domKinematics_newparam::domFloatRef ptarget = daeSafeCast<domKinematics_newparam::domFloat>(daeSidRef(pnewparam->getSIDREF()->getValue(), pnewparam).resolve().elt); 02090 if( !ptarget ) { 02091 ROS_WARN("failed to resolve %s from %s\n", pnewparam->getSIDREF()->getValue(), paddr->getID()); 02092 continue; 02093 } 02094 return ptarget->getValue(); 02095 } 02096 } 02097 } 02098 ROS_WARN_STREAM(str(boost::format("failed to resolve %s\n")%paddr->getParam()->getValue())); 02099 return 0; 02100 } 02101 02102 static bool resolveCommon_float_or_param(daeElementRef pcommon, daeElementRef parent, float& f) 02103 { 02104 daeElement* pfloat = pcommon->getChild("float"); 02105 if( !!pfloat ) { 02106 std::stringstream sfloat(pfloat->getCharData()); 02107 sfloat >> f; 02108 return !!sfloat; 02109 } 02110 daeElement* pparam = pcommon->getChild("param"); 02111 if( !!pparam ) { 02112 if( pparam->hasAttribute("ref") ) { 02113 ROS_WARN_STREAM("cannot process param ref\n"); 02114 } 02115 else { 02116 daeElement* pelt = daeSidRef(pparam->getCharData(),parent).resolve().elt; 02117 if( !!pelt ) { 02118 ROS_WARN_STREAM(str(boost::format("found param ref: %s from %s\n")%pelt->getCharData()%pparam->getCharData())); 02119 } 02120 } 02121 } 02122 return false; 02123 } 02124 02125 static boost::array<double,12> _matrixIdentity() 02126 { 02127 boost::array<double,12> m = {{1,0,0,0,0,1,0,0,0,0,1,0}}; 02128 return m; 02129 }; 02130 02132 static boost::array<double,12> _getTransform(daeElementRef pelt) 02133 { 02134 boost::array<double,12> m = _matrixIdentity(); 02135 domRotateRef protate = daeSafeCast<domRotate>(pelt); 02136 if( !!protate ) { 02137 m = _matrixFromAxisAngle(Vector3(protate->getValue()[0],protate->getValue()[1],protate->getValue()[2]), (double)(protate->getValue()[3]*(M_PI/180.0))); 02138 return m; 02139 } 02140 02141 domTranslateRef ptrans = daeSafeCast<domTranslate>(pelt); 02142 if( !!ptrans ) { 02143 double scale = _GetUnitScale(pelt); 02144 m[3] = ptrans->getValue()[0]*scale; 02145 m[7] = ptrans->getValue()[1]*scale; 02146 m[11] = ptrans->getValue()[2]*scale; 02147 return m; 02148 } 02149 02150 domMatrixRef pmat = daeSafeCast<domMatrix>(pelt); 02151 if( !!pmat ) { 02152 double scale = _GetUnitScale(pelt); 02153 for(int i = 0; i < 3; ++i) { 02154 m[4*i+0] = pmat->getValue()[4*i+0]; 02155 m[4*i+1] = pmat->getValue()[4*i+1]; 02156 m[4*i+2] = pmat->getValue()[4*i+2]; 02157 m[4*i+3] = pmat->getValue()[4*i+3]*scale; 02158 } 02159 return m; 02160 } 02161 02162 domScaleRef pscale = daeSafeCast<domScale>(pelt); 02163 if( !!pscale ) { 02164 m[0] = pscale->getValue()[0]; 02165 m[4*1+1] = pscale->getValue()[1]; 02166 m[4*2+2] = pscale->getValue()[2]; 02167 return m; 02168 } 02169 02170 domLookatRef pcamera = daeSafeCast<domLookat>(pelt); 02171 if( pelt->typeID() == domLookat::ID() ) { 02172 ROS_ERROR_STREAM("look at transform not implemented\n"); 02173 return m; 02174 } 02175 02176 domSkewRef pskew = daeSafeCast<domSkew>(pelt); 02177 if( !!pskew ) { 02178 ROS_ERROR_STREAM("skew transform not implemented\n"); 02179 } 02180 02181 return m; 02182 } 02183 02186 template <typename T> static boost::array<double,12> _getNodeParentTransform(const T pelt) { 02187 domNodeRef pnode = daeSafeCast<domNode>(pelt->getParent()); 02188 if( !pnode ) { 02189 return _matrixIdentity(); 02190 } 02191 return _poseMult(_getNodeParentTransform(pnode), _ExtractFullTransform(pnode)); 02192 } 02193 02195 template <typename T> static boost::array<double,12> _ExtractFullTransform(const T pelt) { 02196 boost::array<double,12> t = _matrixIdentity(); 02197 for(size_t i = 0; i < pelt->getContents().getCount(); ++i) { 02198 t = _poseMult(t, _getTransform(pelt->getContents()[i])); 02199 } 02200 return t; 02201 } 02202 02204 template <typename T> static boost::array<double,12> _ExtractFullTransformFromChildren(const T pelt) { 02205 boost::array<double,12> t = _matrixIdentity(); 02206 daeTArray<daeElementRef> children; pelt->getChildren(children); 02207 for(size_t i = 0; i < children.getCount(); ++i) { 02208 t = _poseMult(t, _getTransform(children[i])); 02209 } 02210 return t; 02211 } 02212 02213 // decompose a matrix into a scale and rigid transform (necessary for model scales) 02214 void _decompose(const boost::array<double,12>& tm, Pose& tout, Vector3& vscale) 02215 { 02216 vscale.x = 1; vscale.y = 1; vscale.z = 1; 02217 tout = _poseFromMatrix(tm); 02218 } 02219 02220 virtual void handleError( daeString msg ) 02221 { 02222 ROS_ERROR("COLLADA error: %s\n", msg); 02223 } 02224 02225 virtual void handleWarning( daeString msg ) 02226 { 02227 ROS_WARN("COLLADA warning: %s\n", msg); 02228 } 02229 02230 inline static double _GetUnitScale(daeElement* pelt) 02231 { 02232 return ((USERDATA*)pelt->getUserData())->scale; 02233 } 02234 02235 domTechniqueRef _ExtractOpenRAVEProfile(const domTechnique_Array& arr) 02236 { 02237 for(size_t i = 0; i < arr.getCount(); ++i) { 02238 if( strcmp(arr[i]->getProfile(), "OpenRAVE") == 0 ) { 02239 return arr[i]; 02240 } 02241 } 02242 return domTechniqueRef(); 02243 } 02244 02246 boost::shared_ptr<std::string> _ExtractInterfaceType(const domExtra_Array& arr) { 02247 for(size_t i = 0; i < arr.getCount(); ++i) { 02248 if( strcmp(arr[i]->getType(),"interface_type") == 0 ) { 02249 domTechniqueRef tec = _ExtractOpenRAVEProfile(arr[i]->getTechnique_array()); 02250 if( !!tec ) { 02251 daeElement* ptype = tec->getChild("interface"); 02252 if( !!ptype ) { 02253 return boost::shared_ptr<std::string>(new std::string(ptype->getCharData())); 02254 } 02255 } 02256 } 02257 } 02258 return boost::shared_ptr<std::string>(); 02259 } 02260 02261 std::string _ExtractLinkName(domLinkRef pdomlink) { 02262 std::string linkname; 02263 if( !!pdomlink ) { 02264 if( !!pdomlink->getName() ) { 02265 linkname = pdomlink->getName(); 02266 } 02267 if( linkname.size() == 0 && !!pdomlink->getID() ) { 02268 linkname = pdomlink->getID(); 02269 } 02270 } 02271 return linkname; 02272 } 02273 02274 bool _checkMathML(daeElementRef pelt,const std::string& type) 02275 { 02276 if( pelt->getElementName()==type ) { 02277 return true; 02278 } 02279 // check the substring after ':' 02280 std::string name = pelt->getElementName(); 02281 std::size_t pos = name.find_last_of(':'); 02282 if( pos == std::string::npos ) { 02283 return false; 02284 } 02285 return name.substr(pos+1)==type; 02286 } 02287 02288 boost::shared_ptr<Joint> _getJointFromRef(xsToken targetref, daeElementRef peltref) { 02289 daeElement* peltjoint = daeSidRef(targetref, peltref).resolve().elt; 02290 domJointRef pdomjoint = daeSafeCast<domJoint> (peltjoint); 02291 02292 if (!pdomjoint) { 02293 domInstance_jointRef pdomijoint = daeSafeCast<domInstance_joint> (peltjoint); 02294 if (!!pdomijoint) { 02295 pdomjoint = daeSafeCast<domJoint> (pdomijoint->getUrl().getElement().cast()); 02296 } 02297 } 02298 02299 if (!pdomjoint || pdomjoint->typeID() != domJoint::ID() || !pdomjoint->getName()) { 02300 ROS_WARN_STREAM(str(boost::format("could not find collada joint %s!\n")%targetref)); 02301 return boost::shared_ptr<Joint>(); 02302 } 02303 02304 boost::shared_ptr<Joint> pjoint = _model->joints_[std::string(pdomjoint->getName())]; 02305 if(!pjoint) { 02306 ROS_WARN_STREAM(str(boost::format("could not find openrave joint %s!\n")%pdomjoint->getName())); 02307 } 02308 return pjoint; 02309 } 02310 02314 static void _ExtractKinematicsVisualBindings(domInstance_with_extraRef viscene, domInstance_kinematics_sceneRef kiscene, KinematicsSceneBindings& bindings) 02315 { 02316 domKinematics_sceneRef kscene = daeSafeCast<domKinematics_scene> (kiscene->getUrl().getElement().cast()); 02317 if (!kscene) { 02318 return; 02319 } 02320 for (size_t imodel = 0; imodel < kiscene->getBind_kinematics_model_array().getCount(); imodel++) { 02321 domArticulated_systemRef articulated_system; // if filled, contains robot-specific information, so create a robot 02322 domBind_kinematics_modelRef kbindmodel = kiscene->getBind_kinematics_model_array()[imodel]; 02323 if (!kbindmodel->getNode()) { 02324 ROS_WARN_STREAM("do not support kinematics models without references to nodes\n"); 02325 continue; 02326 } 02327 02328 // visual information 02329 domNodeRef node = daeSafeCast<domNode>(daeSidRef(kbindmodel->getNode(), viscene->getUrl().getElement()).resolve().elt); 02330 if (!node) { 02331 ROS_WARN_STREAM(str(boost::format("bind_kinematics_model does not reference valid node %s\n")%kbindmodel->getNode())); 02332 continue; 02333 } 02334 02335 // kinematics information 02336 daeElement* pelt = searchBinding(kbindmodel,kscene); 02337 domInstance_kinematics_modelRef kimodel = daeSafeCast<domInstance_kinematics_model>(pelt); 02338 if (!kimodel) { 02339 if( !pelt ) { 02340 ROS_WARN_STREAM("bind_kinematics_model does not reference element\n"); 02341 } 02342 else { 02343 ROS_WARN_STREAM(str(boost::format("bind_kinematics_model cannot find reference to %s:\n")%pelt->getElementName())); 02344 } 02345 continue; 02346 } 02347 bindings.listKinematicsVisualBindings.push_back(std::make_pair(node,kimodel)); 02348 } 02349 // axis info 02350 for (size_t ijoint = 0; ijoint < kiscene->getBind_joint_axis_array().getCount(); ++ijoint) { 02351 domBind_joint_axisRef bindjoint = kiscene->getBind_joint_axis_array()[ijoint]; 02352 daeElementRef pjtarget = daeSidRef(bindjoint->getTarget(), viscene->getUrl().getElement()).resolve().elt; 02353 if (!pjtarget) { 02354 ROS_ERROR_STREAM(str(boost::format("Target Node %s NOT found!!!\n")%bindjoint->getTarget())); 02355 continue; 02356 } 02357 daeElement* pelt = searchBinding(bindjoint->getAxis(),kscene); 02358 domAxis_constraintRef pjointaxis = daeSafeCast<domAxis_constraint>(pelt); 02359 if (!pjointaxis) { 02360 continue; 02361 } 02362 bindings.listAxisBindings.push_back(JointAxisBinding(pjtarget, pjointaxis, bindjoint->getValue(), NULL, NULL)); 02363 } 02364 } 02365 02366 static void _ExtractPhysicsBindings(domCOLLADA::domSceneRef allscene, KinematicsSceneBindings& bindings) 02367 { 02368 for(size_t iphysics = 0; iphysics < allscene->getInstance_physics_scene_array().getCount(); ++iphysics) { 02369 domPhysics_sceneRef pscene = daeSafeCast<domPhysics_scene>(allscene->getInstance_physics_scene_array()[iphysics]->getUrl().getElement().cast()); 02370 for(size_t imodel = 0; imodel < pscene->getInstance_physics_model_array().getCount(); ++imodel) { 02371 domInstance_physics_modelRef ipmodel = pscene->getInstance_physics_model_array()[imodel]; 02372 domPhysics_modelRef pmodel = daeSafeCast<domPhysics_model> (ipmodel->getUrl().getElement().cast()); 02373 domNodeRef nodephysicsoffset = daeSafeCast<domNode>(ipmodel->getParent().getElement().cast()); 02374 for(size_t ibody = 0; ibody < ipmodel->getInstance_rigid_body_array().getCount(); ++ibody) { 02375 LinkBinding lb; 02376 lb.irigidbody = ipmodel->getInstance_rigid_body_array()[ibody]; 02377 lb.node = daeSafeCast<domNode>(lb.irigidbody->getTarget().getElement().cast()); 02378 lb.rigidbody = daeSafeCast<domRigid_body>(daeSidRef(lb.irigidbody->getBody(),pmodel).resolve().elt); 02379 lb.nodephysicsoffset = nodephysicsoffset; 02380 if( !!lb.rigidbody && !!lb.node ) { 02381 bindings.listLinkBindings.push_back(lb); 02382 } 02383 } 02384 } 02385 } 02386 } 02387 02388 02389 size_t _countChildren(daeElement* pelt) { 02390 size_t c = 1; 02391 daeTArray<daeElementRef> children; 02392 pelt->getChildren(children); 02393 for (size_t i = 0; i < children.getCount(); ++i) { 02394 c += _countChildren(children[i]); 02395 } 02396 return c; 02397 } 02398 02399 void _processUserData(daeElement* pelt, double scale) 02400 { 02401 // getChild could be optimized since asset tag is supposed to appear as the first element 02402 domAssetRef passet = daeSafeCast<domAsset> (pelt->getChild("asset")); 02403 if (!!passet && !!passet->getUnit()) { 02404 scale = passet->getUnit()->getMeter(); 02405 } 02406 02407 _vuserdata.push_back(USERDATA(scale)); 02408 pelt->setUserData(&_vuserdata.back()); 02409 daeTArray<daeElementRef> children; 02410 pelt->getChildren(children); 02411 for (size_t i = 0; i < children.getCount(); ++i) { 02412 if (children[i] != passet) { 02413 _processUserData(children[i], scale); 02414 } 02415 } 02416 } 02417 02418 USERDATA* _getUserData(daeElement* pelt) 02419 { 02420 BOOST_ASSERT(!!pelt); 02421 void* p = pelt->getUserData(); 02422 BOOST_ASSERT(!!p); 02423 return (USERDATA*)p; 02424 } 02425 02426 // 02427 // openrave math functions (from geometry.h) 02428 // 02429 02430 static Vector3 _poseMult(const Pose& p, const Vector3& v) 02431 { 02432 double ww = 2 * p.rotation.x * p.rotation.x; 02433 double wx = 2 * p.rotation.x * p.rotation.y; 02434 double wy = 2 * p.rotation.x * p.rotation.z; 02435 double wz = 2 * p.rotation.x * p.rotation.w; 02436 double xx = 2 * p.rotation.y * p.rotation.y; 02437 double xy = 2 * p.rotation.y * p.rotation.z; 02438 double xz = 2 * p.rotation.y * p.rotation.w; 02439 double yy = 2 * p.rotation.z * p.rotation.z; 02440 double yz = 2 * p.rotation.z * p.rotation.w; 02441 Vector3 vnew; 02442 vnew.x = (1-xx-yy) * v.x + (wx-yz) * v.y + (wy+xz)*v.z + p.position.x; 02443 vnew.y = (wx+yz) * v.x + (1-ww-yy) * v.y + (xy-wz)*v.z + p.position.y; 02444 vnew.z = (wy-xz) * v.x + (xy+wz) * v.y + (1-ww-xx)*v.z + p.position.z; 02445 return vnew; 02446 } 02447 02448 static Vector3 _poseMult(const boost::array<double,12>& m, const Vector3& v) 02449 { 02450 Vector3 vnew; 02451 vnew.x = m[4*0+0] * v.x + m[4*0+1] * v.y + m[4*0+2] * v.z + m[4*0+3]; 02452 vnew.y = m[4*1+0] * v.x + m[4*1+1] * v.y + m[4*1+2] * v.z + m[4*1+3]; 02453 vnew.z = m[4*2+0] * v.x + m[4*2+1] * v.y + m[4*2+2] * v.z + m[4*2+3]; 02454 return vnew; 02455 } 02456 02457 static boost::array<double,12> _poseMult(const boost::array<double,12>& m0, const boost::array<double,12>& m1) 02458 { 02459 boost::array<double,12> mres; 02460 mres[0*4+0] = m0[0*4+0]*m1[0*4+0]+m0[0*4+1]*m1[1*4+0]+m0[0*4+2]*m1[2*4+0]; 02461 mres[0*4+1] = m0[0*4+0]*m1[0*4+1]+m0[0*4+1]*m1[1*4+1]+m0[0*4+2]*m1[2*4+1]; 02462 mres[0*4+2] = m0[0*4+0]*m1[0*4+2]+m0[0*4+1]*m1[1*4+2]+m0[0*4+2]*m1[2*4+2]; 02463 mres[1*4+0] = m0[1*4+0]*m1[0*4+0]+m0[1*4+1]*m1[1*4+0]+m0[1*4+2]*m1[2*4+0]; 02464 mres[1*4+1] = m0[1*4+0]*m1[0*4+1]+m0[1*4+1]*m1[1*4+1]+m0[1*4+2]*m1[2*4+1]; 02465 mres[1*4+2] = m0[1*4+0]*m1[0*4+2]+m0[1*4+1]*m1[1*4+2]+m0[1*4+2]*m1[2*4+2]; 02466 mres[2*4+0] = m0[2*4+0]*m1[0*4+0]+m0[2*4+1]*m1[1*4+0]+m0[2*4+2]*m1[2*4+0]; 02467 mres[2*4+1] = m0[2*4+0]*m1[0*4+1]+m0[2*4+1]*m1[1*4+1]+m0[2*4+2]*m1[2*4+1]; 02468 mres[2*4+2] = m0[2*4+0]*m1[0*4+2]+m0[2*4+1]*m1[1*4+2]+m0[2*4+2]*m1[2*4+2]; 02469 mres[3] = m1[3] * m0[0] + m1[7] * m0[1] + m1[11] * m0[2] + m0[3]; 02470 mres[7] = m1[3] * m0[4] + m1[7] * m0[5] + m1[11] * m0[6] + m0[7]; 02471 mres[11] = m1[3] * m0[8] + m1[7] * m0[9] + m1[11] * m0[10] + m0[11]; 02472 return mres; 02473 } 02474 02475 static Pose _poseMult(const Pose& p0, const Pose& p1) 02476 { 02477 Pose p; 02478 p.position = _poseMult(p0,p1.position); 02479 p.rotation = _quatMult(p0.rotation,p1.rotation); 02480 return p; 02481 } 02482 02483 static Pose _poseInverse(const Pose& p) 02484 { 02485 Pose pinv; 02486 pinv.rotation.x = -p.rotation.x; 02487 pinv.rotation.y = -p.rotation.y; 02488 pinv.rotation.z = -p.rotation.z; 02489 pinv.rotation.w = p.rotation.w; 02490 Vector3 t = _poseMult(pinv,p.position); 02491 pinv.position.x = -t.x; 02492 pinv.position.y = -t.y; 02493 pinv.position.z = -t.z; 02494 return pinv; 02495 } 02496 02497 static Rotation _quatMult(const Rotation& quat0, const Rotation& quat1) 02498 { 02499 Rotation q; 02500 q.x = quat0.w*quat1.x + quat0.x*quat1.w + quat0.y*quat1.z - quat0.z*quat1.y; 02501 q.y = quat0.w*quat1.y + quat0.y*quat1.w + quat0.z*quat1.x - quat0.x*quat1.z; 02502 q.z = quat0.w*quat1.z + quat0.z*quat1.w + quat0.x*quat1.y - quat0.y*quat1.x; 02503 q.w = quat0.w*quat1.w - quat0.x*quat1.x - quat0.y*quat1.y - quat0.z*quat1.z; 02504 double fnorm = std::sqrt(q.x*q.x+q.y*q.y+q.z*q.z+q.w*q.w); 02505 // don't touch the divides 02506 q.x /= fnorm; 02507 q.y /= fnorm; 02508 q.z /= fnorm; 02509 q.w /= fnorm; 02510 return q; 02511 } 02512 02513 static boost::array<double,12> _matrixFromAxisAngle(const Vector3& axis, double angle) 02514 { 02515 return _matrixFromQuat(_quatFromAxisAngle(axis.x,axis.y,axis.z,angle)); 02516 } 02517 02518 static boost::array<double,12> _matrixFromQuat(const Rotation& quat) 02519 { 02520 boost::array<double,12> m; 02521 double qq1 = 2*quat.x*quat.x; 02522 double qq2 = 2*quat.y*quat.y; 02523 double qq3 = 2*quat.z*quat.z; 02524 m[4*0+0] = 1 - qq2 - qq3; 02525 m[4*0+1] = 2*(quat.x*quat.y - quat.w*quat.z); 02526 m[4*0+2] = 2*(quat.x*quat.z + quat.w*quat.y); 02527 m[4*0+3] = 0; 02528 m[4*1+0] = 2*(quat.x*quat.y + quat.w*quat.z); 02529 m[4*1+1] = 1 - qq1 - qq3; 02530 m[4*1+2] = 2*(quat.y*quat.z - quat.w*quat.x); 02531 m[4*1+3] = 0; 02532 m[4*2+0] = 2*(quat.x*quat.z - quat.w*quat.y); 02533 m[4*2+1] = 2*(quat.y*quat.z + quat.w*quat.x); 02534 m[4*2+2] = 1 - qq1 - qq2; 02535 m[4*2+3] = 0; 02536 return m; 02537 } 02538 02539 static Pose _poseFromMatrix(const boost::array<double,12>& m) 02540 { 02541 Pose t; 02542 t.rotation = _quatFromMatrix(m); 02543 t.position.x = m[3]; 02544 t.position.y = m[7]; 02545 t.position.z = m[11]; 02546 return t; 02547 } 02548 02549 static boost::array<double,12> _matrixFromPose(const Pose& t) 02550 { 02551 boost::array<double,12> m = _matrixFromQuat(t.rotation); 02552 m[3] = t.position.x; 02553 m[7] = t.position.y; 02554 m[11] = t.position.z; 02555 return m; 02556 } 02557 02558 static Rotation _quatFromAxisAngle(double x, double y, double z, double angle) 02559 { 02560 Rotation q; 02561 double axislen = std::sqrt(x*x+y*y+z*z); 02562 if( axislen == 0 ) { 02563 return q; 02564 } 02565 angle *= 0.5; 02566 double sang = std::sin(angle)/axislen; 02567 q.w = std::cos(angle); 02568 q.x = x*sang; 02569 q.y = y*sang; 02570 q.z = z*sang; 02571 return q; 02572 } 02573 02574 static Rotation _quatFromMatrix(const boost::array<double,12>& mat) 02575 { 02576 Rotation rot; 02577 double tr = mat[4*0+0] + mat[4*1+1] + mat[4*2+2]; 02578 if (tr >= 0) { 02579 rot.w = tr + 1; 02580 rot.x = (mat[4*2+1] - mat[4*1+2]); 02581 rot.y = (mat[4*0+2] - mat[4*2+0]); 02582 rot.z = (mat[4*1+0] - mat[4*0+1]); 02583 } 02584 else { 02585 // find the largest diagonal element and jump to the appropriate case 02586 if (mat[4*1+1] > mat[4*0+0]) { 02587 if (mat[4*2+2] > mat[4*1+1]) { 02588 rot.z = (mat[4*2+2] - (mat[4*0+0] + mat[4*1+1])) + 1; 02589 rot.x = (mat[4*2+0] + mat[4*0+2]); 02590 rot.y = (mat[4*1+2] + mat[4*2+1]); 02591 rot.w = (mat[4*1+0] - mat[4*0+1]); 02592 } 02593 else { 02594 rot.y = (mat[4*1+1] - (mat[4*2+2] + mat[4*0+0])) + 1; 02595 rot.z = (mat[4*1+2] + mat[4*2+1]); 02596 rot.x = (mat[4*0+1] + mat[4*1+0]); 02597 rot.w = (mat[4*0+2] - mat[4*2+0]); 02598 } 02599 } 02600 else if (mat[4*2+2] > mat[4*0+0]) { 02601 rot.z = (mat[4*2+2] - (mat[4*0+0] + mat[4*1+1])) + 1; 02602 rot.x = (mat[4*2+0] + mat[4*0+2]); 02603 rot.y = (mat[4*1+2] + mat[4*2+1]); 02604 rot.w = (mat[4*1+0] - mat[4*0+1]); 02605 } 02606 else { 02607 rot.x = (mat[4*0+0] - (mat[4*1+1] + mat[4*2+2])) + 1; 02608 rot.y = (mat[4*0+1] + mat[4*1+0]); 02609 rot.z = (mat[4*2+0] + mat[4*0+2]); 02610 rot.w = (mat[4*2+1] - mat[4*1+2]); 02611 } 02612 } 02613 double fnorm = std::sqrt(rot.x*rot.x+rot.y*rot.y+rot.z*rot.z+rot.w*rot.w); 02614 // don't touch the divides 02615 rot.x /= fnorm; 02616 rot.y /= fnorm; 02617 rot.z /= fnorm; 02618 rot.w /= fnorm; 02619 return rot; 02620 } 02621 02622 static double _dot3(const Vector3& v0, const Vector3& v1) 02623 { 02624 return v0.x*v1.x + v0.y*v1.y + v0.z*v1.z; 02625 } 02626 static Vector3 _cross3(const Vector3& v0, const Vector3& v1) 02627 { 02628 Vector3 v; 02629 v.x = v0.y * v1.z - v0.z * v1.y; 02630 v.y = v0.z * v1.x - v0.x * v1.z; 02631 v.z = v0.x * v1.y - v0.y * v1.x; 02632 return v; 02633 } 02634 static Vector3 _sub3(const Vector3& v0, const Vector3& v1) 02635 { 02636 Vector3 v; 02637 v.x = v0.x-v1.x; 02638 v.y = v0.y-v1.y; 02639 v.z = v0.z-v1.z; 02640 return v; 02641 } 02642 static Vector3 _add3(const Vector3& v0, const Vector3& v1) 02643 { 02644 Vector3 v; 02645 v.x = v0.x+v1.x; 02646 v.y = v0.y+v1.y; 02647 v.z = v0.z+v1.z; 02648 return v; 02649 } 02650 static Vector3 _normalize3(const Vector3& v0) 02651 { 02652 Vector3 v; 02653 double norm = std::sqrt(v0.x*v0.x+v0.y*v0.y+v0.z*v0.z); 02654 v.x = v0.x/norm; 02655 v.y = v0.y/norm; 02656 v.z = v0.z/norm; 02657 return v; 02658 } 02659 02660 DAE* _collada; 02661 domCOLLADA* _dom; 02662 std::vector<USERDATA> _vuserdata; // all userdata 02663 int _nGlobalSensorId, _nGlobalManipulatorId; 02664 std::string _filename; 02665 std::string _resourcedir; 02666 boost::shared_ptr<ModelInterface> _model; 02667 02668 }; 02669 02670 02671 02672 02673 boost::shared_ptr<ModelInterface> parseCollada(const std::string &xml_str) 02674 { 02675 boost::shared_ptr<ModelInterface> model(new ModelInterface); 02676 02677 ColladaModelReader reader(model); 02678 if (!reader.InitFromData(xml_str)) 02679 model.reset(); 02680 return model; 02681 } 02682 }