#ifndef BTMULTIBODYFROMURDF_HPP #define BTMULTIBODYFROMURDF_HPP #include "btBulletDynamicsCommon.h" #include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h" #include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h" #include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h" #include "BulletDynamics/Featherstone/btMultiBodyPoint2Point.h" #include "../../examples/CommonInterfaces/CommonGUIHelperInterface.h" #include "../../examples/Importers/ImportURDFDemo/BulletUrdfImporter.h" #include "../../examples/Importers/ImportURDFDemo/URDF2Bullet.h" #include "../../examples/Importers/ImportURDFDemo/MyMultiBodyCreator.h" #include "../../examples/Importers/ImportURDFDemo/URDF2Bullet.h" /// Create a btMultiBody model from URDF. /// This is adapted from Bullet URDF loader example class MyBtMultiBodyFromURDF { public: /// ctor /// @param gravity gravitational acceleration (in world frame) /// @param base_fixed if true, the root body is treated as fixed, /// if false, it is treated as floating MyBtMultiBodyFromURDF(const btVector3 &gravity, const bool base_fixed) : m_gravity(gravity), m_base_fixed(base_fixed) { m_broadphase = 0x0; m_dispatcher = 0x0; m_solver = 0x0; m_collisionConfiguration = 0x0; m_dynamicsWorld = 0x0; m_multibody = 0x0; } /// dtor ~MyBtMultiBodyFromURDF() { delete m_dynamicsWorld; delete m_solver; delete m_broadphase; delete m_dispatcher; delete m_collisionConfiguration; delete m_multibody; } /// @param name path to urdf file void setFileName(const std::string name) { m_filename = name; } /// load urdf file and build btMultiBody model void init() { this->createEmptyDynamicsWorld(); m_dynamicsWorld->setGravity(m_gravity); BulletURDFImporter urdf_importer(&m_nogfx,0); URDFImporterInterface &u2b(urdf_importer); bool loadOk = u2b.loadURDF(m_filename.c_str(), m_base_fixed); if (loadOk) { btTransform identityTrans; identityTrans.setIdentity(); MyMultiBodyCreator creation(&m_nogfx); const bool use_multibody = true; ConvertURDF2Bullet(u2b, creation, identityTrans, m_dynamicsWorld, use_multibody, u2b.getPathPrefix()); m_multibody = creation.getBulletMultiBody(); m_dynamicsWorld->stepSimulation(1. / 240., 0); } } /// @return pointer to the btMultiBody model btMultiBody *getBtMultiBody() { return m_multibody; } private: // internal utility function void createEmptyDynamicsWorld() { m_collisionConfiguration = new btDefaultCollisionConfiguration(); /// use the default collision dispatcher. For parallel processing you can use a diffent /// dispatcher (see Extras/BulletMultiThreaded) m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); m_broadphase = new btDbvtBroadphase(); m_solver = new btMultiBodyConstraintSolver; m_dynamicsWorld = new btMultiBodyDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration); m_dynamicsWorld->setGravity(m_gravity); } btBroadphaseInterface *m_broadphase; btCollisionDispatcher *m_dispatcher; btMultiBodyConstraintSolver *m_solver; btDefaultCollisionConfiguration *m_collisionConfiguration; btMultiBodyDynamicsWorld *m_dynamicsWorld; std::string m_filename; DummyGUIHelper m_nogfx; btMultiBody *m_multibody; const btVector3 m_gravity; const bool m_base_fixed; }; #endif // BTMULTIBODYFROMURDF_HPP