add InverseDynamics example for example browser

add CMake support for BulletInverseDynamics and BulletInverseDynamicsUtils
This commit is contained in:
Erwin Coumans
2015-11-24 11:12:02 -08:00
parent b4701613c8
commit 03cc4f0554
12 changed files with 347 additions and 99 deletions

View File

@@ -278,6 +278,7 @@ ENDIF()
set (BULLET_CONFIG_CMAKE_PATH lib${LIB_SUFFIX}/cmake/bullet ) set (BULLET_CONFIG_CMAKE_PATH lib${LIB_SUFFIX}/cmake/bullet )
list (APPEND BULLET_LIBRARIES LinearMath) list (APPEND BULLET_LIBRARIES LinearMath)
list (APPEND BULLET_LIBRARIES BulletInverseDynamics)
list (APPEND BULLET_LIBRARIES BulletCollision) list (APPEND BULLET_LIBRARIES BulletCollision)
list (APPEND BULLET_LIBRARIES BulletDynamics) list (APPEND BULLET_LIBRARIES BulletDynamics)
list (APPEND BULLET_LIBRARIES BulletSoftBody) list (APPEND BULLET_LIBRARIES BulletSoftBody)

View File

@@ -1,4 +1,4 @@
SUBDIRS( Serialize ConvexDecomposition HACD GIMPACTUtils ) SUBDIRS( Serialize InverseDynamics ConvexDecomposition HACD GIMPACTUtils )
#Maya Dynamica plugin is moved to http://dynamica.googlecode.com #Maya Dynamica plugin is moved to http://dynamica.googlecode.com

View File

@@ -0,0 +1,17 @@
#ifndef BULLET_INVERSE_DYNAMICS_UTILS_COMMON_H
#define BULLET_INVERSE_DYNAMICS_UTILS_COMMON_H
#include "CoilCreator.hpp"
#include "MultiBodyTreeCreator.hpp"
#include "btMultiBodyFromURDF.hpp"
#include "DillCreator.hpp"
#include "MultiBodyTreeDebugGraph.hpp"
#include "btMultiBodyTreeCreator.hpp"
#include "IDRandomUtil.hpp"
#include "SimpleTreeCreator.hpp"
#include "invdyn_bullet_comparison.hpp"
#include "MultiBodyNameMap.hpp"
#include "User2InternalIndex.hpp"
#endif//BULLET_INVERSE_DYNAMICS_UTILS_COMMON_H

View File

@@ -0,0 +1,45 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
)
ADD_LIBRARY(
BulletInverseDynamicsUtils
CoilCreator.cpp
MultiBodyTreeCreator.cpp
btMultiBodyTreeCreator.cpp
DillCreator.cpp
MultiBodyTreeDebugGraph.cpp
invdyn_bullet_comparison.cpp
IDRandomUtil.cpp
SimpleTreeCreator.cpp
MultiBodyNameMap.cpp
User2InternalIndex.cpp
)
SET_TARGET_PROPERTIES(BulletInverseDynamicsUtils PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletInverseDynamicsUtils PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(BulletInverseDynamicsUtils LinearMath)
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_EXTRA_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
#FILES_MATCHING requires CMake 2.6
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletInverseDynamicsUtils DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletInverseDynamicsUtils DESTINATION lib${LIB_SUFFIX})
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN
".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletInverseDynamicsUtils PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletInverseDynamicsUtils PROPERTIES PUBLIC_HEADER "BulletInverseDynamicsUtilsCommon.h" )
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_EXTRA_LIBS)

Binary file not shown.

View File

@@ -25,7 +25,7 @@ struct SliderParams
m_callback(0), m_callback(0),
m_paramValuePointer(targetValuePointer), m_paramValuePointer(targetValuePointer),
m_userPointer(0), m_userPointer(0),
m_clampToNotches(false), m_clampToNotches(true),
m_showValues(true) m_showValues(true)
{ {
} }

View File

@@ -36,6 +36,8 @@ SET(App_ExampleBrowser_SRCS
../SharedMemory/PhysicsServerCommandProcessor.h ../SharedMemory/PhysicsServerCommandProcessor.h
../BasicDemo/BasicExample.cpp ../BasicDemo/BasicExample.cpp
../BasicDemo/BasicExample.h ../BasicDemo/BasicExample.h
../InverseDynamics/InverseDynamicsExample.cpp
../InverseDynamics/InverseDynamicsExample.h
../ForkLift/ForkLiftDemo.cpp ../ForkLift/ForkLiftDemo.cpp
../ForkLift/ForkLiftDemo.h ../ForkLift/ForkLiftDemo.h
../Tutorial/Tutorial.cpp ../Tutorial/Tutorial.cpp
@@ -191,7 +193,7 @@ SET(App_ExampleBrowser_SRCS
) )
LINK_LIBRARIES( LINK_LIBRARIES(
Bullet3Common BulletSoftBody BulletDynamics BulletCollision LinearMath OpenGLWindow gwen ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY} Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}
) )
IF (WIN32) IF (WIN32)

View File

@@ -40,7 +40,7 @@
#include "../Tutorial/Tutorial.h" #include "../Tutorial/Tutorial.h"
#include "../Tutorial/Dof6ConstraintTutorial.h" #include "../Tutorial/Dof6ConstraintTutorial.h"
#include "../MultiThreading/MultiThreadingExample.h" #include "../MultiThreading/MultiThreadingExample.h"
//#include "../InverseDynamics/InverseDynamicsExample.h" #include "../InverseDynamics/InverseDynamicsExample.h"
#ifdef ENABLE_LUA #ifdef ENABLE_LUA
#include "../LuaDemo/LuaPhysicsSetup.h" #include "../LuaDemo/LuaPhysicsSetup.h"
@@ -110,9 +110,11 @@ static ExampleEntry gDefaultExamples[]=
ExampleEntry(1,"Constraint Feedback", "The example shows how to receive joint reaction forces in a btMultiBody. Also the applied impulse is available for a btMultiBodyJointMotor", MultiBodyConstraintFeedbackCreateFunc), ExampleEntry(1,"Constraint Feedback", "The example shows how to receive joint reaction forces in a btMultiBody. Also the applied impulse is available for a btMultiBodyJointMotor", MultiBodyConstraintFeedbackCreateFunc),
ExampleEntry(1,"Inverted Pendulum PD","Keep an inverted pendulum up using open loop PD control", InvertedPendulumPDControlCreateFunc), ExampleEntry(1,"Inverted Pendulum PD","Keep an inverted pendulum up using open loop PD control", InvertedPendulumPDControlCreateFunc),
// ExampleEntry(0,"Inverse Dynamics"), ExampleEntry(0,"Inverse Dynamics"),
// ExampleEntry(1,"Inverse Dynamics URDF", "write some explanation", InverseDynamicsExampleCreateFunc,BT_ID_LOAD_URDF), ExampleEntry(1,"Inverse Dynamics URDF", "Create a btMultiBody from URDF. Create an inverse MultiBodyTree model from that. Use either decoupled PD control or computed torque control using the inverse model to track joint position targets", InverseDynamicsExampleCreateFunc,BT_ID_LOAD_URDF),
// ExampleEntry(1,"Inverse Dynamics Prog", "write some explanation2", InverseDynamicsExampleCreateFunc,BT_ID_PROGRAMMATICALLY), ExampleEntry(1,"Inverse Dynamics Prog", "Create a btMultiBody programatically. Create an inverse MultiBodyTree model from that. Use either decoupled PD control or computed torque control using the inverse model to track joint position targets", InverseDynamicsExampleCreateFunc,BT_ID_PROGRAMMATICALLY),
ExampleEntry(0,"Tutorial"), ExampleEntry(0,"Tutorial"),
ExampleEntry(1,"Constant Velocity","Free moving rigid body, without external or constraint forces", TutorialCreateFunc,TUT_VELOCITY), ExampleEntry(1,"Constant Velocity","Free moving rigid body, without external or constraint forces", TutorialCreateFunc,TUT_VELOCITY),

View File

@@ -29,7 +29,7 @@
end end
links{"gwen", "OpenGL_Window","BulletSoftBody", "BulletDynamics","BulletCollision","LinearMath","Bullet3Common"} links{"gwen", "OpenGL_Window","BulletSoftBody", "BulletInverseDynamicsUtils", "BulletInverseDynamics", "BulletDynamics","BulletCollision","LinearMath","Bullet3Common"}
initOpenGL() initOpenGL()
initGlew() initGlew()

View File

@@ -32,45 +32,68 @@ subject to the following restrictions:
#include "../CommonInterfaces/CommonRigidBodyBase.h" #include "../CommonInterfaces/CommonRigidBodyBase.h"
//those are static global to make it easy for the GUI to tweak them #include "BulletInverseDynamics/IDConfig.hpp"
static btScalar radius(0.2); #include "../Extras/InverseDynamics/btMultiBodyTreeCreator.hpp"
static btScalar kp = 100;
static btScalar kd = 20; #include "../RenderingExamples/TimeSeriesCanvas.h"
static btScalar maxForce = 100;
#include <unistd.h>
#include <vector>
// the UI interface makes it easier to use static variables & free functions
// as parameters and callbacks
static btScalar kp =10*10;
static btScalar kd = 2*10;
static bool useInverseModel = true;
static std::vector<btScalar> qd;
static std::vector<std::string> qd_name;
static std::vector<std::string> q_name;
void toggleUseInverseModel(int buttonId, bool buttonState, void* userPointer){
useInverseModel=!useInverseModel;
// todo(thomas) is there a way to get a toggle button with changing text?
b3Printf("switched inverse model %s", useInverseModel?"on":"off");
}
class InverseDynamicsExample : public CommonMultiBodyBase class InverseDynamicsExample : public CommonMultiBodyBase
{ {
btInverseDynamicsExampleOptions m_option; btInverseDynamicsExampleOptions m_option;
btMultiBody* m_multiBody; btMultiBody* m_multiBody;
btInverseDynamics::MultiBodyTree *m_inverseModel;
TimeSeriesCanvas* m_timeSeriesCanvas;
public: public:
InverseDynamicsExample(struct GUIHelperInterface* helper, btInverseDynamicsExampleOptions option); InverseDynamicsExample(struct GUIHelperInterface* helper, btInverseDynamicsExampleOptions option);
virtual ~InverseDynamicsExample(); virtual ~InverseDynamicsExample();
virtual void initPhysics(); virtual void initPhysics();
virtual void stepSimulation(float deltaTime); virtual void stepSimulation(float deltaTime);
void setFileName(const char* urdfFileName); void setFileName(const char* urdfFileName);
virtual void resetCamera() virtual void resetCamera()
{ {
float dist = 3.5; float dist = 3.5;
float pitch = -136; float pitch = -136;
float yaw = 28; float yaw = 28;
float targetPos[3]={0.47,0,-0.64}; float targetPos[3]={0.47,0,-0.64};
m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]); m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
} }
}; };
InverseDynamicsExample::InverseDynamicsExample(struct GUIHelperInterface* helper, btInverseDynamicsExampleOptions option) InverseDynamicsExample::InverseDynamicsExample(struct GUIHelperInterface* helper, btInverseDynamicsExampleOptions option)
:CommonMultiBodyBase(helper), :CommonMultiBodyBase(helper),
m_option(option), m_option(option),
m_multiBody(0) m_multiBody(0),
m_inverseModel(0),
m_timeSeriesCanvas(0)
{ {
} }
InverseDynamicsExample::~InverseDynamicsExample() InverseDynamicsExample::~InverseDynamicsExample()
{ {
delete m_multiBody;
delete m_inverseModel;
delete m_timeSeriesCanvas;
} }
//todo(erwincoumans) Quick hack, reference to InvertedPendulumPDControl implementation. Will create a separate header/source file for this. //todo(erwincoumans) Quick hack, reference to InvertedPendulumPDControl implementation. Will create a separate header/source file for this.
@@ -78,89 +101,181 @@ btMultiBody* createInvertedPendulumMultiBody(btMultiBodyDynamicsWorld* world, GU
void InverseDynamicsExample::initPhysics() void InverseDynamicsExample::initPhysics()
{ {
//roboticists like Z up //roboticists like Z up
int upAxis = 2; int upAxis = 2;
m_guiHelper->setUpAxis(upAxis); m_guiHelper->setUpAxis(upAxis);
createEmptyDynamicsWorld(); createEmptyDynamicsWorld();
btVector3 gravity(0,0,0); btVector3 gravity(0,0,0);
gravity[upAxis]=-9.8; gravity[upAxis]=-9.8;
m_dynamicsWorld->setGravity(gravity); m_dynamicsWorld->setGravity(gravity);
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld); m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
{ {
SliderParams slider("Kp",&kp); SliderParams slider("Kp",&kp);
slider.m_minVal=-200; slider.m_minVal=0;
slider.m_maxVal=200; slider.m_maxVal=2000;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider);
} }
{ {
SliderParams slider("Kd",&kd); SliderParams slider("Kd",&kd);
slider.m_minVal=-50; slider.m_minVal=0;
slider.m_maxVal=50; slider.m_maxVal=50;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider); m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider);
}
{
SliderParams slider("max force",&maxForce);
slider.m_minVal=0;
slider.m_maxVal=100;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider);
} }
switch (m_option) if (m_option == BT_ID_PROGRAMMATICALLY)
{ {
case BT_ID_LOAD_URDF: ButtonParams button("toggle inverse model",0,true);
{ button.m_callback = toggleUseInverseModel;
BulletURDFImporter u2b(m_guiHelper); m_guiHelper->getParameterInterface()->registerButtonParameter(button);
bool loadOk = u2b.loadURDF("kuka_lwr/kuka.urdf"); }
if (loadOk)
{
int rootLinkIndex = u2b.getRootLinkIndex(); switch (m_option)
b3Printf("urdf root link index = %d\n",rootLinkIndex); {
MyMultiBodyCreator creation(m_guiHelper); case BT_ID_LOAD_URDF:
btTransform identityTrans; {
identityTrans.setIdentity(); BulletURDFImporter u2b(m_guiHelper);
ConvertURDF2Bullet(u2b,creation, identityTrans,m_dynamicsWorld,true,u2b.getPathPrefix()); bool loadOk = u2b.loadURDF("kuka_lwr/kuka.urdf");
m_multiBody = creation.getBulletMultiBody(); if (loadOk)
if (m_multiBody) {
{ int rootLinkIndex = u2b.getRootLinkIndex();
//kuka without joint control/constraints will gain energy explode soon due to timestep/integrator b3Printf("urdf root link index = %d\n",rootLinkIndex);
//temporarily set some extreme damping factors until we have some joint control or constraints MyMultiBodyCreator creation(m_guiHelper);
m_multiBody->setAngularDamping(0.99); btTransform identityTrans;
m_multiBody->setLinearDamping(0.99); identityTrans.setIdentity();
b3Printf("Root link name = %s",u2b.getLinkName(u2b.getRootLinkIndex()).c_str()); ConvertURDF2Bullet(u2b,creation, identityTrans,m_dynamicsWorld,true,u2b.getPathPrefix());
} m_multiBody = creation.getBulletMultiBody();
} if (m_multiBody)
break; {
} //kuka without joint control/constraints will gain energy explode soon due to timestep/integrator
case BT_ID_PROGRAMMATICALLY: //temporarily set some extreme damping factors until we have some joint control or constraints
{ m_multiBody->setAngularDamping(0*0.99);
btTransform baseWorldTrans; m_multiBody->setLinearDamping(0*0.99);
baseWorldTrans.setIdentity(); b3Printf("Root link name = %s",u2b.getLinkName(u2b.getRootLinkIndex()).c_str());
m_multiBody = createInvertedPendulumMultiBody(m_dynamicsWorld, m_guiHelper, baseWorldTrans); }
break; }
} break;
default: }
{ case BT_ID_PROGRAMMATICALLY:
b3Error("Unknown option in InverseDynamicsExample::initPhysics"); {
b3Assert(0); btTransform baseWorldTrans;
} baseWorldTrans.setIdentity();
}; m_multiBody = createInvertedPendulumMultiBody(m_dynamicsWorld, m_guiHelper, baseWorldTrans);
break;
}
default:
{
b3Error("Unknown option in InverseDynamicsExample::initPhysics");
b3Assert(0);
}
};
if(m_multiBody) {
{
m_timeSeriesCanvas = new TimeSeriesCanvas(m_guiHelper->getAppInterface()->m_2dCanvasInterface,512,230, "q time series");
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());
for(std::size_t dof=0;dof<qd.size();dof++) {
qd[dof] = 0;
char tmp[25];
snprintf(tmp,25,"q_desired[%zu]",dof);
qd_name[dof] = tmp;
SliderParams slider(qd_name[dof].c_str(),&qd[dof]);
slider.m_minVal=-3.14;
slider.m_maxVal=3.14;
snprintf(tmp,25,"q[%zu]",dof);
q_name[dof] = tmp;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider);
m_timeSeriesCanvas->addDataSource(q_name[dof].c_str(), 255,0,0);
}
}
} }
void InverseDynamicsExample::stepSimulation(float deltaTime) void InverseDynamicsExample::stepSimulation(float deltaTime)
{ {
if (m_dynamicsWorld) static uint64_t call=0;
{ call++;
m_dynamicsWorld->stepSimulation(deltaTime,10,1./240.); if(m_multiBody) {
} const int num_dofs=m_multiBody->getNumDofs();
btInverseDynamics::vecx nu(num_dofs), qdot(num_dofs), q(num_dofs),joint_force(num_dofs);
btInverseDynamics::vecx pd_control(num_dofs);
// compute joint forces from one of two control laws:
// 1) "computed torque" control, which gives perfect, decoupled,
// linear second order error dynamics per dof in case of a
// perfect model and (and negligible time discretization effects)
// 2) decoupled PD control per joint, without a model
for(int dof=0;dof<num_dofs;dof++) {
q(dof) = m_multiBody->getJointPos(dof);
qdot(dof)= m_multiBody->getJointVel(dof);
const btScalar qd_dot=0;
const btScalar qd_ddot=0;
m_timeSeriesCanvas->insertDataAtCurrentTime(q[dof],dof,true);
// pd_control is either desired joint torque for pd control,
// or the feedback contribution to nu
pd_control(dof) = kd*(qd_dot-qdot(dof)) + kp*(qd[dof]-q(dof));
// nu is the desired joint acceleration for computed torque control
nu(dof) = qd_ddot + pd_control(dof);
}
// calculate joint forces corresponding to desired accelerations nu
if(-1 != m_inverseModel->calculateInverseDynamics(q,qdot,nu,&joint_force)) {
for(int dof=0;dof<num_dofs;dof++) {
if(useInverseModel) {
//joint_force(dof) += damping*dot_q(dof);
// use inverse model: apply joint force corresponding to
// desired acceleration nu
m_multiBody->addJointTorque(dof,joint_force(dof));
} else {
// no model: just apply PD control law
m_multiBody->addJointTorque(dof,pd_control(dof));
}
}
}
}
if (m_timeSeriesCanvas)
m_timeSeriesCanvas->nextTick();
//todo: joint damping for btMultiBody, tune parameters
// step the simulation
if (m_dynamicsWorld)
{
// todo(thomas) check that this is correct:
// want to advance by 10ms, with 1ms timesteps
m_dynamicsWorld->stepSimulation(1e-3,0);//,1e-3);
}
} }
CommonExampleInterface* InverseDynamicsExampleCreateFunc(CommonExampleOptions& options) CommonExampleInterface* InverseDynamicsExampleCreateFunc(CommonExampleOptions& options)
{ {
return new InverseDynamicsExample(options.m_guiHelper, btInverseDynamicsExampleOptions(options.m_option)); return new InverseDynamicsExample(options.m_guiHelper, btInverseDynamicsExampleOptions(options.m_option));
} }

View File

@@ -0,0 +1,66 @@
INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/src )
SET(BulletInverseDynamics_SRCS
IDMath.cpp
MultiBodyTree.cpp
details/MultiBodyTreeInitCache.cpp
details/MultiBodyTreeImpl.cpp
)
SET(BulletInverseDynamicsRoot_HDRS
IDConfig.hpp
IDConfigEigen.hpp
IDMath.hpp
IDConfigBuiltin.hpp
IDErrorMessages.hpp
MultiBodyTree.hpp
)
SET(BulletInverseDynamicsDetails_HDRS
details/IDEigenInterface.hpp
details/IDMatVec.hpp
details/IDLinearMathInterface.hpp
details/MultiBodyTreeImpl.hpp
details/MultiBodyTreeInitCache.hpp
)
SET(BulletInverseDynamics_HDRS
${BulletInverseDynamicsRoot_HDRS}
${BulletInverseDynamicsDetails_HDRS}
)
ADD_LIBRARY(BulletInverseDynamics ${BulletInverseDynamics_SRCS} ${BulletInverseDynamics_HDRS})
SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(BulletInverseDynamics LinearMath)
ENDIF (BUILD_SHARED_LIBS)
IF (INSTALL_LIBS)
IF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
#INSTALL of other files requires CMake 2.6
IF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletInverseDynamics DESTINATION .)
ELSE (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
INSTALL(TARGETS BulletInverseDynamics RUNTIME DESTINATION bin
LIBRARY DESTINATION lib${LIB_SUFFIX}
ARCHIVE DESTINATION lib${LIB_SUFFIX})
INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
DESTINATION ${INCLUDE_INSTALL_DIR} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE PATTERN "CMakeFiles" EXCLUDE)
INSTALL(FILES ../btBulletCollisionCommon.h
DESTINATION ${INCLUDE_INSTALL_DIR}/BulletInverseDynamics)
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.5)
IF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES FRAMEWORK true)
SET_TARGET_PROPERTIES(BulletInverseDynamics PROPERTIES PUBLIC_HEADER "${BulletInverseDynamicsRoot_HDRS}")
# Have to list out sub-directories manually:
SET_PROPERTY(SOURCE ${BulletInverseDynamicsDetails_HDRS} PROPERTY MACOSX_PACKAGE_LOCATION Headers/details)
ENDIF (APPLE AND BUILD_SHARED_LIBS AND FRAMEWORK)
ENDIF (NOT INTERNAL_CREATE_DISTRIBUTABLE_MSVC_PROJECTFILES)
ENDIF (INSTALL_LIBS)

View File

@@ -3,7 +3,7 @@ IF(BUILD_BULLET3)
SUBDIRS( Bullet3OpenCL Bullet3Serialize/Bullet2FileLoader Bullet3Dynamics Bullet3Collision Bullet3Geometry Bullet3Common ) SUBDIRS( Bullet3OpenCL Bullet3Serialize/Bullet2FileLoader Bullet3Dynamics Bullet3Collision Bullet3Geometry Bullet3Common )
ENDIF(BUILD_BULLET3) ENDIF(BUILD_BULLET3)
SUBDIRS( BulletSoftBody BulletCollision BulletDynamics LinearMath ) SUBDIRS( BulletSoftBody BulletInverseDynamics BulletCollision BulletDynamics LinearMath )
IF(INSTALL_LIBS) IF(INSTALL_LIBS)