summaryrefslogtreecommitdiff
path: root/examples/BlockSolver/BlockSolverExample.cpp
blob: 61685079aa04db21cf8d6e3361bde6c3f16cb283 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
#include "BlockSolverExample.h"
#include "BulletDynamics/MLCPSolvers/btDantzigSolver.h"
#include "BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h"
#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
#include "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h"
#include "btBlockSolver.h"
//for URDF import support
#include "../Importers/ImportURDFDemo/BulletUrdfImporter.h"
#include "../Importers/ImportURDFDemo/MyMultiBodyCreator.h"
#include "../Importers/ImportURDFDemo/URDF2Bullet.h"
#include "../CommonInterfaces/CommonMultiBodyBase.h"

class BlockSolverExample : public CommonMultiBodyBase
{
	int m_option;

public:
	BlockSolverExample(GUIHelperInterface* helper, int option);
	virtual ~BlockSolverExample();

	virtual void initPhysics();

	virtual void stepSimulation(float deltaTime);

	virtual void resetCamera()
	{
		float dist = 3;
		float pitch = -35;
		float yaw = 50;
		float targetPos[3] = {0, 0, .1};
		m_guiHelper->resetCamera(dist, yaw, pitch, targetPos[0], targetPos[1], targetPos[2]);
	}

	void createMultiBodyStack();
	btMultiBody* createMultiBody(btScalar mass, const btTransform& trans, btCollisionShape* collisionShape);
	btMultiBody* loadRobot(std::string filepath);
};

BlockSolverExample::BlockSolverExample(GUIHelperInterface* helper, int option)
	: CommonMultiBodyBase(helper),
	  m_option(option)
{
	m_guiHelper->setUpAxis(2);
}

BlockSolverExample::~BlockSolverExample()
{
	// Do nothing
}

void BlockSolverExample::stepSimulation(float deltaTime)
{
	//use a smaller internal timestep, there are stability issues
	btScalar internalTimeStep = 1. / 240.f;
	m_dynamicsWorld->stepSimulation(deltaTime, 10, internalTimeStep);
}

void BlockSolverExample::initPhysics()
{
	///collision configuration contains default setup for memory, collision setup
	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();

	btMLCPSolverInterface* mlcp;
	if (m_option & BLOCK_SOLVER_SI)
	{
		btAssert(!m_solver);
		m_solver = new btMultiBodyConstraintSolver;
		b3Printf("Constraint Solver: Sequential Impulse");
	}
	if (m_option & BLOCK_SOLVER_MLCP_PGS)
	{
		btAssert(!m_solver);
		mlcp = new btSolveProjectedGaussSeidel();
		m_solver = new btMultiBodyMLCPConstraintSolver(mlcp);
		b3Printf("Constraint Solver: MLCP + PGS");
	}
	if (m_option & BLOCK_SOLVER_MLCP_DANTZIG)
	{
		btAssert(!m_solver);
		mlcp = new btDantzigSolver();
		m_solver = new btMultiBodyMLCPConstraintSolver(mlcp);
		b3Printf("Constraint Solver: MLCP + Dantzig");
	}
	if (m_option & BLOCK_SOLVER_BLOCK)
	{
		m_solver = new btBlockSolver();
	}

	btAssert(m_solver);

	btMultiBodyDynamicsWorld* world = new btMultiBodyDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
	m_dynamicsWorld = world;
	m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
	m_dynamicsWorld->setGravity(btVector3(0, 0, -10));
	m_dynamicsWorld->getSolverInfo().m_numIterations = 50;
	m_dynamicsWorld->getSolverInfo().m_globalCfm = btScalar(1e-6);  //todo: what value is good?

	if (m_option & BLOCK_SOLVER_SCENE_MB_STACK)
	{
		createMultiBodyStack();
	}

	m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
}

void BlockSolverExample::createMultiBodyStack()
{
	///create a few basic rigid bodies
	bool loadPlaneFromURDF = false;
	if (loadPlaneFromURDF)
	{
		btMultiBody* mb = loadRobot("plane.urdf");
		printf("!\n");
	}
	else
	{
		btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.), btScalar(50.), btScalar(50.)));
		m_collisionShapes.push_back(groundShape);
		btScalar mass = 0;
		btTransform tr;
		tr.setIdentity();
		tr.setOrigin(btVector3(0, 0, -50));
		btMultiBody* body = createMultiBody(mass, tr, groundShape);
	}

	for (int i = 0; i < 10; i++)
	{
		btBoxShape* boxShape = createBoxShape(btVector3(btScalar(.1), btScalar(.1), btScalar(.1)));
		m_collisionShapes.push_back(boxShape);
		btScalar mass = 1;
		if (i == 9)
			mass = 100;
		btTransform tr;
		tr.setIdentity();
		tr.setOrigin(btVector3(0, 0, 0.1 + i * 0.2));
		btMultiBody* body = createMultiBody(mass, tr, boxShape);
	}
	if (/* DISABLES CODE */ (0))
	{
		btMultiBody* mb = loadRobot("cube_small.urdf");
		btTransform tr;
		tr.setIdentity();
		tr.setOrigin(btVector3(0, 0, 1.));
		mb->setBaseWorldTransform(tr);
	}
}

btMultiBody* BlockSolverExample::createMultiBody(btScalar mass, const btTransform& trans, btCollisionShape* collisionShape)
{
	btVector3 inertia;
	collisionShape->calculateLocalInertia(mass, inertia);

	bool canSleep = false;
	bool isDynamic = mass > 0;
	btMultiBody* mb = new btMultiBody(0, mass, inertia, !isDynamic, canSleep);
	btMultiBodyLinkCollider* collider = new btMultiBodyLinkCollider(mb, -1);
	collider->setWorldTransform(trans);
	mb->setBaseWorldTransform(trans);

	collider->setCollisionShape(collisionShape);

	int collisionFilterGroup = isDynamic ? int(btBroadphaseProxy::DefaultFilter) : int(btBroadphaseProxy::StaticFilter);
	int collisionFilterMask = isDynamic ? int(btBroadphaseProxy::AllFilter) : int(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);

	this->m_dynamicsWorld->addCollisionObject(collider, collisionFilterGroup, collisionFilterMask);
	mb->setBaseCollider(collider);

	mb->finalizeMultiDof();

	this->m_dynamicsWorld->addMultiBody(mb);
	m_dynamicsWorld->forwardKinematics();
	return mb;
}

btMultiBody* BlockSolverExample::loadRobot(std::string filepath)
{
	btMultiBody* m_multiBody = 0;
	BulletURDFImporter u2b(m_guiHelper, 0, 0, 1, 0);
	bool loadOk = u2b.loadURDF(filepath.c_str());  // 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)
		{
			b3Printf("Root link name = %s", u2b.getLinkName(u2b.getRootLinkIndex()).c_str());
		}
	}
	return m_multiBody;
}

CommonExampleInterface* BlockSolverExampleCreateFunc(CommonExampleOptions& options)
{
	return new BlockSolverExample(options.m_guiHelper, options.m_option);
}