bool PhysicsServer::loadUrdf(const char* fileName, const btVector3& pos, const btQuaternion& orn, bool useMultiBody, bool useFixedBase) { MyURDFImporter u2b(m_guiHelper); bool loadOk = u2b.loadURDF(fileName); if (loadOk) { b3Printf("loaded %s OK!", fileName); btTransform tr; tr.setIdentity(); tr.setOrigin(pos); tr.setRotation(orn); int rootLinkIndex = u2b.getRootLinkIndex(); // printf("urdf root link index = %d\n",rootLinkIndex); MyMultiBodyCreator creation(m_guiHelper); ConvertURDF2Bullet(u2b,creation, tr,m_dynamicsWorld,useMultiBody,u2b.getPathPrefix()); btMultiBody* mb = creation.getBulletMultiBody(); return true; } return false; }
static int gLoadMultiBodyFromUrdf(lua_State *L) { int argc = lua_gettop(L); if (argc==4) { if (!lua_isuserdata(L,1)) { std::cerr << "error: first argument to b3CreateRigidbody should be world"; return 0; } luaL_checktype(L,3, LUA_TTABLE); btVector3 pos = getLuaVectorArg(L,3); btQuaternion orn = getLuaQuaternionArg(L,4); btDiscreteDynamicsWorld* world = (btDiscreteDynamicsWorld*) lua_touserdata(L,1); if (world != sLuaDemo->m_dynamicsWorld) { std::cerr << "error: first argument expected to be a world"; return 0; } const char* fileName = lua_tostring(L,2); #if 1 BulletURDFImporter u2b(sLuaDemo->m_guiHelper); bool loadOk = u2b.loadURDF(fileName); if (loadOk) { b3Printf("loaded %s OK!", fileName); btTransform tr; tr.setIdentity(); tr.setOrigin(pos); tr.setRotation(orn); int rootLinkIndex = u2b.getRootLinkIndex(); // printf("urdf root link index = %d\n",rootLinkIndex); MyMultiBodyCreator creation(sLuaDemo->m_guiHelper); bool m_useMultiBody = true; ConvertURDF2Bullet(u2b,creation, tr,sLuaDemo->m_dynamicsWorld,m_useMultiBody,u2b.getPathPrefix()); btMultiBody* mb = creation.getBulletMultiBody(); if (mb) { lua_pushlightuserdata (L, mb); return 1; } } else { b3Printf("can't find %s",fileName); } #endif } return 0; }
/// load urdf file and build btMultiBody model void init() { this->createEmptyDynamicsWorld(); m_dynamicsWorld->setGravity(m_gravity); b3BulletDefaultFileIO fileIO; BulletURDFImporter urdf_importer(&m_nogfx, 0, &fileIO, 1, 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); } }
void ImportUrdfSetup::initPhysics() { m_guiHelper->setUpAxis(m_upAxis); this->createEmptyDynamicsWorld(); //m_dynamicsWorld->getSolverInfo().m_numIterations = 100; m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); m_dynamicsWorld->getDebugDrawer()->setDebugMode( btIDebugDraw::DBG_DrawConstraints +btIDebugDraw::DBG_DrawContactPoints +btIDebugDraw::DBG_DrawAabb );//+btIDebugDraw::DBG_DrawConstraintLimits); if (m_guiHelper->getParameterInterface()) { SliderParams slider("Gravity", &m_grav); slider.m_minVal = -10; slider.m_maxVal = 10; m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); } BulletURDFImporter u2b(m_guiHelper, 0); bool loadOk = u2b.loadURDF(m_fileName); #ifdef TEST_MULTIBODY_SERIALIZATION //test to serialize a multibody to disk or shared memory, with base, link and joint names btSerializer* s = new btDefaultSerializer; #endif //TEST_MULTIBODY_SERIALIZATION if (loadOk) { //printTree(u2b,u2b.getRootLinkIndex()); //u2b.printTree(); btTransform identityTrans; identityTrans.setIdentity(); { //todo: move these internal API called inside the 'ConvertURDF2Bullet' call, hidden from the user //int rootLinkIndex = u2b.getRootLinkIndex(); //b3Printf("urdf root link index = %d\n",rootLinkIndex); MyMultiBodyCreator creation(m_guiHelper); ConvertURDF2Bullet(u2b,creation, identityTrans,m_dynamicsWorld,m_useMultiBody,u2b.getPathPrefix()); m_data->m_rb = creation.getRigidBody(); m_data->m_mb = creation.getBulletMultiBody(); btMultiBody* mb = m_data->m_mb; for (int i = 0; i < u2b.getNumAllocatedCollisionShapes(); i++) { m_collisionShapes.push_back(u2b.getAllocatedCollisionShape(i)); } if (m_useMultiBody && mb ) { std::string* name = new std::string(u2b.getLinkName(u2b.getRootLinkIndex())); m_nameMemory.push_back(name); #ifdef TEST_MULTIBODY_SERIALIZATION s->registerNameForPointer(name->c_str(),name->c_str()); #endif//TEST_MULTIBODY_SERIALIZATION mb->setBaseName(name->c_str()); //create motors for each btMultiBody joint int numLinks = mb->getNumLinks(); for (int i=0;i<numLinks;i++) { int mbLinkIndex = i; int urdfLinkIndex = creation.m_mb2urdfLink[mbLinkIndex]; std::string* jointName = new std::string(u2b.getJointName(urdfLinkIndex)); std::string* linkName = new std::string(u2b.getLinkName(urdfLinkIndex).c_str()); #ifdef TEST_MULTIBODY_SERIALIZATION s->registerNameForPointer(jointName->c_str(),jointName->c_str()); s->registerNameForPointer(linkName->c_str(),linkName->c_str()); #endif//TEST_MULTIBODY_SERIALIZATION m_nameMemory.push_back(jointName); m_nameMemory.push_back(linkName); mb->getLink(i).m_linkName = linkName->c_str(); mb->getLink(i).m_jointName = jointName->c_str(); if (mb->getLink(mbLinkIndex).m_jointType==btMultibodyLink::eRevolute ||mb->getLink(mbLinkIndex).m_jointType==btMultibodyLink::ePrismatic ) { if (m_data->m_numMotors<MAX_NUM_MOTORS) { char motorName[1024]; sprintf(motorName,"%s q'", jointName->c_str()); btScalar* motorVel = &m_data->m_motorTargetVelocities[m_data->m_numMotors]; *motorVel = 0.f; SliderParams slider(motorName,motorVel); slider.m_minVal=-4; slider.m_maxVal=4; m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); float maxMotorImpulse = 10.1f; btMultiBodyJointMotor* motor = new btMultiBodyJointMotor(mb,mbLinkIndex,0,0,maxMotorImpulse); //motor->setMaxAppliedImpulse(0); m_data->m_jointMotors[m_data->m_numMotors]=motor; m_dynamicsWorld->addMultiBodyConstraint(motor); m_data->m_numMotors++; } } } } else { if (1) { //create motors for each generic joint int num6Dof = creation.getNum6DofConstraints(); for (int i=0;i<num6Dof;i++) { btGeneric6DofSpring2Constraint* c = creation.get6DofConstraint(i); if (c->getUserConstraintPtr()) { GenericConstraintUserInfo* jointInfo = (GenericConstraintUserInfo*)c->getUserConstraintPtr(); if ((jointInfo->m_urdfJointType ==URDFRevoluteJoint) || (jointInfo->m_urdfJointType ==URDFPrismaticJoint) || (jointInfo->m_urdfJointType ==URDFContinuousJoint)) { int urdfLinkIndex = jointInfo->m_urdfIndex; std::string jointName = u2b.getJointName(urdfLinkIndex); char motorName[1024]; sprintf(motorName,"%s q'", jointName.c_str()); btScalar* motorVel = &m_data->m_motorTargetVelocities[m_data->m_numMotors]; *motorVel = 0.f; SliderParams slider(motorName,motorVel); slider.m_minVal=-4; slider.m_maxVal=4; m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); m_data->m_generic6DofJointMotors[m_data->m_numMotors]=c; bool motorOn = true; c->enableMotor(jointInfo->m_jointAxisIndex,motorOn); c->setMaxMotorForce(jointInfo->m_jointAxisIndex,10000); c->setTargetVelocity(jointInfo->m_jointAxisIndex,0); m_data->m_numMotors++; } } } } } } //the btMultiBody support is work-in-progress :-) for (int i=0;i<m_dynamicsWorld->getNumMultiBodyConstraints();i++) { m_dynamicsWorld->getMultiBodyConstraint(i)->finalizeMultiDof(); } bool createGround=true; if (createGround) { btVector3 groundHalfExtents(20,20,20); groundHalfExtents[m_upAxis]=1.f; btBoxShape* box = new btBoxShape(groundHalfExtents); m_collisionShapes.push_back(box); box->initializePolyhedralFeatures(); m_guiHelper->createCollisionShapeGraphicsObject(box); btTransform start; start.setIdentity(); btVector3 groundOrigin(0,0,0); groundOrigin[m_upAxis]=-2.5; start.setOrigin(groundOrigin); btRigidBody* body = createRigidBody(0,start,box); //m_dynamicsWorld->removeRigidBody(body); // m_dynamicsWorld->addRigidBody(body,2,1); btVector3 color(0.5,0.5,0.5); m_guiHelper->createRigidBodyGraphicsObject(body,color); } } #ifdef TEST_MULTIBODY_SERIALIZATION m_dynamicsWorld->serialize(s); b3ResourcePath p; char resourcePath[1024]; if (p.findResourcePath("r2d2_multibody.bullet",resourcePath,1024)) { FILE* f = fopen(resourcePath,"wb"); fwrite(s->getBufferPointer(),s->getCurrentBufferSize(),1,f); fclose(f); } #endif//TEST_MULTIBODY_SERIALIZATION }
void ImportSDFSetup::initPhysics() { int upAxis = 2; m_guiHelper->setUpAxis(upAxis); this->createEmptyDynamicsWorld(); //m_dynamicsWorld->getSolverInfo().m_numIterations = 100; m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); m_dynamicsWorld->getDebugDrawer()->setDebugMode( btIDebugDraw::DBG_DrawConstraints +btIDebugDraw::DBG_DrawContactPoints +btIDebugDraw::DBG_DrawAabb );//+btIDebugDraw::DBG_DrawConstraintLimits); btVector3 gravity(0,0,0); gravity[upAxis]=-9.8; m_dynamicsWorld->setGravity(gravity); BulletURDFImporter u2b(m_guiHelper); bool loadOk = u2b.loadSDF(m_fileName); if (loadOk) { //printTree(u2b,u2b.getRootLinkIndex()); //u2b.printTree(); btTransform identityTrans; identityTrans.setIdentity(); for (int m =0; m<u2b.getNumModels();m++) { u2b.activateModel(m); btMultiBody* mb = 0; //todo: move these internal API called inside the 'ConvertURDF2Bullet' call, hidden from the user int rootLinkIndex = u2b.getRootLinkIndex(); b3Printf("urdf root link index = %d\n",rootLinkIndex); MyMultiBodyCreator creation(m_guiHelper); ConvertURDF2Bullet(u2b,creation, identityTrans,m_dynamicsWorld,m_useMultiBody,u2b.getPathPrefix()); mb = creation.getBulletMultiBody(); } for (int i=0;i<m_dynamicsWorld->getNumMultiBodyConstraints();i++) { m_dynamicsWorld->getMultiBodyConstraint(i)->finalizeMultiDof(); } bool createGround=true; if (createGround) { btVector3 groundHalfExtents(20,20,20); groundHalfExtents[upAxis]=1.f; btBoxShape* box = new btBoxShape(groundHalfExtents); box->initializePolyhedralFeatures(); m_guiHelper->createCollisionShapeGraphicsObject(box); btTransform start; start.setIdentity(); btVector3 groundOrigin(0,0,0); groundOrigin[upAxis]=-2.5; start.setOrigin(groundOrigin); btRigidBody* body = createRigidBody(0,start,box); //m_dynamicsWorld->removeRigidBody(body); // m_dynamicsWorld->addRigidBody(body,2,1); btVector3 color(0.5,0.5,0.5); m_guiHelper->createRigidBodyGraphicsObject(body,color); } ///this extra stepSimulation call makes sure that all the btMultibody transforms are properly propagates. m_dynamicsWorld->stepSimulation(1. / 240., 0);// 1., 10, 1. / 240.); } }
void ImportSDFSetup::initPhysics() { int upAxis = 2; m_guiHelper->setUpAxis(upAxis); this->createEmptyDynamicsWorld(); //m_dynamicsWorld->getSolverInfo().m_numIterations = 100; m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); m_dynamicsWorld->getDebugDrawer()->setDebugMode( btIDebugDraw::DBG_DrawConstraints + btIDebugDraw::DBG_DrawContactPoints + btIDebugDraw::DBG_DrawAabb); //+btIDebugDraw::DBG_DrawConstraintLimits); btVector3 gravity(0, 0, 0); gravity[upAxis] = -9.8; m_dynamicsWorld->setGravity(gravity); BulletURDFImporter u2b(m_guiHelper, 0, 0, 1, 0); bool loadOk = u2b.loadSDF(m_fileName); if (loadOk) { //printTree(u2b,u2b.getRootLinkIndex()); //u2b.printTree(); btTransform rootTrans; rootTrans.setIdentity(); for (int m = 0; m < u2b.getNumModels(); m++) { u2b.activateModel(m); btMultiBody* mb = 0; //todo: move these internal API called inside the 'ConvertURDF2Bullet' call, hidden from the user //int rootLinkIndex = u2b.getRootLinkIndex(); //b3Printf("urdf root link index = %d\n",rootLinkIndex); MyMultiBodyCreator creation(m_guiHelper); u2b.getRootTransformInWorld(rootTrans); ConvertURDF2Bullet(u2b, creation, rootTrans, m_dynamicsWorld, m_useMultiBody, u2b.getPathPrefix(), CUF_USE_SDF); mb = creation.getBulletMultiBody(); if (m_useMultiBody && mb) { std::string* name = new std::string(u2b.getLinkName(u2b.getRootLinkIndex())); m_nameMemory.push_back(name); #ifdef TEST_MULTIBODY_SERIALIZATION s->registerNameForPointer(name->c_str(), name->c_str()); #endif //TEST_MULTIBODY_SERIALIZATION mb->setBaseName(name->c_str()); //create motors for each btMultiBody joint int numLinks = mb->getNumLinks(); for (int i = 0; i < numLinks; i++) { int mbLinkIndex = i; int urdfLinkIndex = creation.m_mb2urdfLink[mbLinkIndex]; std::string* jointName = new std::string(u2b.getJointName(urdfLinkIndex)); std::string* linkName = new std::string(u2b.getLinkName(urdfLinkIndex).c_str()); #ifdef TEST_MULTIBODY_SERIALIZATION s->registerNameForPointer(jointName->c_str(), jointName->c_str()); s->registerNameForPointer(linkName->c_str(), linkName->c_str()); #endif //TEST_MULTIBODY_SERIALIZATION m_nameMemory.push_back(jointName); m_nameMemory.push_back(linkName); mb->getLink(i).m_linkName = linkName->c_str(); mb->getLink(i).m_jointName = jointName->c_str(); if (mb->getLink(mbLinkIndex).m_jointType == btMultibodyLink::eRevolute || mb->getLink(mbLinkIndex).m_jointType == btMultibodyLink::ePrismatic) { if (m_data->m_numMotors < MAX_NUM_MOTORS) { char motorName[1024]; sprintf(motorName, "%s q'", jointName->c_str()); btScalar* motorVel = &m_data->m_motorTargetVelocities[m_data->m_numMotors]; *motorVel = 0.f; SliderParams slider(motorName, motorVel); slider.m_minVal = -4; slider.m_maxVal = 4; m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); float maxMotorImpulse = 10.1f; btMultiBodyJointMotor* motor = new btMultiBodyJointMotor(mb, mbLinkIndex, 0, 0, maxMotorImpulse); //motor->setMaxAppliedImpulse(0); m_data->m_jointMotors[m_data->m_numMotors] = motor; m_dynamicsWorld->addMultiBodyConstraint(motor); m_data->m_numMotors++; } } } } } for (int i = 0; i < m_dynamicsWorld->getNumMultiBodyConstraints(); i++) { m_dynamicsWorld->getMultiBodyConstraint(i)->finalizeMultiDof(); } bool createGround = true; if (createGround) { btVector3 groundHalfExtents(20, 20, 20); groundHalfExtents[upAxis] = 1.f; btBoxShape* box = new btBoxShape(groundHalfExtents); box->initializePolyhedralFeatures(); m_guiHelper->createCollisionShapeGraphicsObject(box); btTransform start; start.setIdentity(); btVector3 groundOrigin(0, 0, 0); groundOrigin[upAxis] = -2.5; start.setOrigin(groundOrigin); btRigidBody* body = createRigidBody(0, start, box); //m_dynamicsWorld->removeRigidBody(body); // m_dynamicsWorld->addRigidBody(body,2,1); btVector3 color(0.5, 0.5, 0.5); m_guiHelper->createRigidBodyGraphicsObject(body, color); } ///this extra stepSimulation call makes sure that all the btMultibody transforms are properly propagates. m_dynamicsWorld->stepSimulation(1. / 240., 0); // 1., 10, 1. / 240.); } }
bool PhysicsServerSharedMemory::loadUrdf(const char* fileName, const btVector3& pos, const btQuaternion& orn, bool useMultiBody, bool useFixedBase) { btAssert(m_data->m_dynamicsWorld); if (!m_data->m_dynamicsWorld) { b3Error("loadUrdf: No valid m_dynamicsWorld"); return false; } BulletURDFImporter u2b(m_data->m_guiHelper); bool loadOk = u2b.loadURDF(fileName, useFixedBase); if (loadOk) { b3Printf("loaded %s OK!", fileName); btTransform tr; tr.setIdentity(); tr.setOrigin(pos); tr.setRotation(orn); //int rootLinkIndex = u2b.getRootLinkIndex(); // printf("urdf root link index = %d\n",rootLinkIndex); MyMultiBodyCreator creation(m_data->m_guiHelper); ConvertURDF2Bullet(u2b,creation, tr,m_data->m_dynamicsWorld,useMultiBody,u2b.getPathPrefix()); btMultiBody* mb = creation.getBulletMultiBody(); if (useMultiBody) { if (mb) { createJointMotors(mb); //serialize the btMultiBody and send the data to the client. This is one way to get the link/joint names across the (shared memory) wire UrdfLinkNameMapUtil* util = new UrdfLinkNameMapUtil; m_data->m_urdfLinkNameMapper.push_back(util); util->m_mb = mb; util->m_memSerializer = new btDefaultSerializer(SHARED_MEMORY_MAX_STREAM_CHUNK_SIZE,(unsigned char*)m_data->m_testBlock1->m_bulletStreamDataServerToClient); //disable serialization of the collision objects (they are too big, and the client likely doesn't need them); util->m_memSerializer->m_skipPointers.insert(mb->getBaseCollider(),0); for (int i=0;i<mb->getNumLinks();i++) { //disable serialization of the collision objects util->m_memSerializer->m_skipPointers.insert(mb->getLink(i).m_collider,0); int urdfLinkIndex = creation.m_mb2urdfLink[i]; std::string* linkName = new std::string(u2b.getLinkName(urdfLinkIndex).c_str()); m_data->m_strings.push_back(linkName); util->m_memSerializer->registerNameForPointer(linkName->c_str(),linkName->c_str()); mb->getLink(i).m_linkName = linkName->c_str(); std::string* jointName = new std::string(u2b.getJointName(urdfLinkIndex).c_str()); m_data->m_strings.push_back(jointName); util->m_memSerializer->registerNameForPointer(jointName->c_str(),jointName->c_str()); mb->getLink(i).m_jointName = jointName->c_str(); } std::string* baseName = new std::string(u2b.getLinkName(u2b.getRootLinkIndex())); m_data->m_strings.push_back(baseName); util->m_memSerializer->registerNameForPointer(baseName->c_str(),baseName->c_str()); mb->setBaseName(baseName->c_str()); util->m_memSerializer->insertHeader(); int len = mb->calculateSerializeBufferSize(); btChunk* chunk = util->m_memSerializer->allocate(len,1); const char* structType = mb->serialize(chunk->m_oldPtr, util->m_memSerializer); util->m_memSerializer->finalizeChunk(chunk,structType,BT_MULTIBODY_CODE,mb); return true; } else { b3Warning("No multibody loaded from URDF. Could add btRigidBody+btTypedConstraint solution later."); return false; } } else { btAssert(0); return true; } } return false; }
void InverseDynamicsExample::initPhysics() { //roboticists like Z up int upAxis = 2; m_guiHelper->setUpAxis(upAxis); createEmptyDynamicsWorld(); btVector3 gravity(0,0,0); // gravity[upAxis]=-9.8; m_dynamicsWorld->setGravity(gravity); m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); { SliderParams slider("Kp",&kp); slider.m_minVal=0; slider.m_maxVal=2000; if (m_guiHelper->getParameterInterface()) m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); } { SliderParams slider("Kd",&kd); slider.m_minVal=0; slider.m_maxVal=50; if (m_guiHelper->getParameterInterface()) m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); } if (m_option == BT_ID_PROGRAMMATICALLY) { ButtonParams button("toggle inverse model",0,true); button.m_callback = toggleUseInverseModel; m_guiHelper->getParameterInterface()->registerButtonParameter(button); } switch (m_option) { case BT_ID_LOAD_URDF: { BulletURDFImporter u2b(m_guiHelper,0,1); bool loadOk = u2b.loadURDF("kuka_iiwa/model.urdf");// lwr / kuka.urdf"); if (loadOk) { int rootLinkIndex = u2b.getRootLinkIndex(); b3Printf("urdf root link index = %d\n",rootLinkIndex); MyMultiBodyCreator creation(m_guiHelper); btTransform identityTrans; identityTrans.setIdentity(); ConvertURDF2Bullet(u2b,creation, identityTrans,m_dynamicsWorld,true,u2b.getPathPrefix()); for (int i = 0; i < u2b.getNumAllocatedCollisionShapes(); i++) { m_collisionShapes.push_back(u2b.getAllocatedCollisionShape(i)); } m_multiBody = creation.getBulletMultiBody(); if (m_multiBody) { //kuka without joint control/constraints will gain energy explode soon due to timestep/integrator //temporarily set some extreme damping factors until we have some joint control or constraints m_multiBody->setAngularDamping(0*0.99); m_multiBody->setLinearDamping(0*0.99); b3Printf("Root link name = %s",u2b.getLinkName(u2b.getRootLinkIndex()).c_str()); } } break; } case BT_ID_PROGRAMMATICALLY: { btTransform baseWorldTrans; baseWorldTrans.setIdentity(); m_multiBody = createInvertedPendulumMultiBody(m_dynamicsWorld, m_guiHelper, baseWorldTrans, false); break; } default: { b3Error("Unknown option in InverseDynamicsExample::initPhysics"); b3Assert(0); } }; if(m_multiBody) { { if (m_guiHelper->getAppInterface() && m_guiHelper->getParameterInterface()) { m_timeSeriesCanvas = new TimeSeriesCanvas(m_guiHelper->getAppInterface()->m_2dCanvasInterface,512,230, "Joint Space Trajectory"); m_timeSeriesCanvas ->setupTimeSeries(3,100, 0); } } // construct inverse model btInverseDynamics::btMultiBodyTreeCreator id_creator; if (-1 == id_creator.createFromBtMultiBody(m_multiBody, false)) { b3Error("error creating tree\n"); } else { m_inverseModel = btInverseDynamics::CreateMultiBodyTree(id_creator); } // add joint target controls qd.resize(m_multiBody->getNumDofs()); qd_name.resize(m_multiBody->getNumDofs()); q_name.resize(m_multiBody->getNumDofs()); if (m_timeSeriesCanvas && m_guiHelper->getParameterInterface()) { for(std::size_t dof=0;dof<qd.size();dof++) { qd[dof] = 0; char tmp[25]; sprintf(tmp,"q_desired[%lu]",dof); qd_name[dof] = tmp; SliderParams slider(qd_name[dof].c_str(),&qd[dof]); slider.m_minVal=-3.14; slider.m_maxVal=3.14; sprintf(tmp,"q[%lu]",dof); q_name[dof] = tmp; m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); btVector4 color = sJointCurveColors[dof&7]; m_timeSeriesCanvas->addDataSource(q_name[dof].c_str(), color[0]*255,color[1]*255,color[2]*255); } } } m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld); }