1 /*************************************************************************
3 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
4 * All rights reserved. Email: russ@q12.org Web: www.q12.org *
6 * This library is free software; you can redistribute it and/or *
7 * modify it under the terms of EITHER: *
8 * (1) The GNU Lesser General Public License as published by the Free *
9 * Software Foundation; either version 2.1 of the License, or (at *
10 * your option) any later version. The text of the GNU Lesser *
11 * General Public License is included with this library in the *
13 * (2) The BSD-style license that is included with this library in *
14 * the file LICENSE-BSD.TXT. *
16 * This library is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
19 * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
21 *************************************************************************/
25 buggy with suspension.
26 this also shows you how to use geom groups.
32 #include <drawstuff/drawstuff.h>
33 #include "texturepath.h"
36 #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
39 // select correct drawing functions
42 #define dsDrawBox dsDrawBoxD
43 #define dsDrawSphere dsDrawSphereD
44 #define dsDrawCylinder dsDrawCylinderD
45 #define dsDrawCapsule dsDrawCapsuleD
51 #define LENGTH 0.7 // chassis length
52 #define WIDTH 0.5 // chassis width
53 #define HEIGHT 0.2 // chassis height
54 #define RADIUS 0.18 // wheel radius
55 #define STARTZ 0.5 // starting height of chassis
56 #define CMASS 1 // chassis mass
57 #define WMASS 0.2 // wheel mass
60 // dynamics and collision objects (chassis, 3 wheels, environment)
62 static dWorldID world
;
63 static dSpaceID space
;
64 static dBodyID body
[4];
65 static dJointID joint
[3]; // joint[0] is the front wheel
66 static dJointGroupID contactgroup
;
67 static dGeomID ground
;
68 static dSpaceID car_space
;
69 static dGeomID box
[1];
70 static dGeomID sphere
[3];
71 static dGeomID ground_box
;
74 // things that the user controls
76 static dReal speed
=0,steer
=0; // user commands
80 // this is called by dSpaceCollide when two objects in space are
81 // potentially colliding.
83 static void nearCallback (void *data
, dGeomID o1
, dGeomID o2
)
87 // only collide things with the ground
88 int g1
= (o1
== ground
|| o1
== ground_box
);
89 int g2
= (o2
== ground
|| o2
== ground_box
);
90 if (!(g1
^ g2
)) return;
94 n
= dCollide (o1
,o2
,N
,&contact
[0].geom
,sizeof(dContact
));
97 contact
[i
].surface
.mode
= dContactSlip1
| dContactSlip2
|
98 dContactSoftERP
| dContactSoftCFM
| dContactApprox1
;
99 contact
[i
].surface
.mu
= dInfinity
;
100 contact
[i
].surface
.slip1
= 0.1;
101 contact
[i
].surface
.slip2
= 0.1;
102 contact
[i
].surface
.soft_erp
= 0.5;
103 contact
[i
].surface
.soft_cfm
= 0.3;
104 dJointID c
= dJointCreateContact (world
,contactgroup
,&contact
[i
]);
106 dGeomGetBody(contact
[i
].geom
.g1
),
107 dGeomGetBody(contact
[i
].geom
.g2
));
113 // start simulation - set viewpoint
117 dAllocateODEDataForThread(dAllocateMaskAll
);
119 static float xyz
[3] = {0.8317f
,-0.9817f
,0.8000f
};
120 static float hpr
[3] = {121.0000f
,-27.5000f
,0.0000f
};
121 dsSetViewpoint (xyz
,hpr
);
122 printf ("Press:\t'a' to increase speed.\n"
123 "\t'z' to decrease speed.\n"
124 "\t',' to steer left.\n"
125 "\t'.' to steer right.\n"
126 "\t' ' to reset speed and steering.\n"
127 "\t'1' to save the current state to 'state.dif'.\n");
131 // called when a key pressed
133 static void command (int cmd
)
153 FILE *f
= fopen ("state.dif","wt");
155 dWorldExportDIF (world
,f
,"");
165 static void simLoop (int pause
)
170 dJointSetHinge2Param (joint
[0],dParamVel2
,-speed
);
171 dJointSetHinge2Param (joint
[0],dParamFMax2
,0.1);
174 dReal v
= steer
- dJointGetHinge2Angle1 (joint
[0]);
175 if (v
> 0.1) v
= 0.1;
176 if (v
< -0.1) v
= -0.1;
178 dJointSetHinge2Param (joint
[0],dParamVel
,v
);
179 dJointSetHinge2Param (joint
[0],dParamFMax
,0.2);
180 dJointSetHinge2Param (joint
[0],dParamLoStop
,-0.75);
181 dJointSetHinge2Param (joint
[0],dParamHiStop
,0.75);
182 dJointSetHinge2Param (joint
[0],dParamFudgeFactor
,0.1);
184 dSpaceCollide (space
,0,&nearCallback
);
185 dWorldStep (world
,0.05);
187 // remove all contact joints
188 dJointGroupEmpty (contactgroup
);
192 dsSetTexture (DS_WOOD
);
193 dReal sides
[3] = {LENGTH
,WIDTH
,HEIGHT
};
194 dsDrawBox (dBodyGetPosition(body
[0]),dBodyGetRotation(body
[0]),sides
);
196 for (i
=1; i
<=3; i
++) dsDrawCylinder (dBodyGetPosition(body
[i
]),
197 dBodyGetRotation(body
[i
]),0.02f
,RADIUS
);
200 dGeomBoxGetLengths (ground_box
,ss
);
201 dsDrawBox (dGeomGetPosition(ground_box
),dGeomGetRotation(ground_box
),ss
);
204 printf ("%.10f %.10f %.10f %.10f\n",
205 dJointGetHingeAngle (joint[1]),
206 dJointGetHingeAngle (joint[2]),
207 dJointGetHingeAngleRate (joint[1]),
208 dJointGetHingeAngleRate (joint[2]));
213 int main (int argc
, char **argv
)
218 // setup pointers to drawstuff callback functions
220 fn
.version
= DS_VERSION
;
223 fn
.command
= &command
;
225 fn
.path_to_textures
= DRAWSTUFF_TEXTURE_PATH
;
229 world
= dWorldCreate();
230 space
= dHashSpaceCreate (0);
231 contactgroup
= dJointGroupCreate (0);
232 dWorldSetGravity (world
,0,0,-0.5);
233 ground
= dCreatePlane (space
,0,0,1,0);
236 body
[0] = dBodyCreate (world
);
237 dBodySetPosition (body
[0],0,0,STARTZ
);
238 dMassSetBox (&m
,1,LENGTH
,WIDTH
,HEIGHT
);
239 dMassAdjust (&m
,CMASS
);
240 dBodySetMass (body
[0],&m
);
241 box
[0] = dCreateBox (0,LENGTH
,WIDTH
,HEIGHT
);
242 dGeomSetBody (box
[0],body
[0]);
245 for (i
=1; i
<=3; i
++) {
246 body
[i
] = dBodyCreate (world
);
248 dQFromAxisAndAngle (q
,1,0,0,M_PI
*0.5);
249 dBodySetQuaternion (body
[i
],q
);
250 dMassSetSphere (&m
,1,RADIUS
);
251 dMassAdjust (&m
,WMASS
);
252 dBodySetMass (body
[i
],&m
);
253 sphere
[i
-1] = dCreateSphere (0,RADIUS
);
254 dGeomSetBody (sphere
[i
-1],body
[i
]);
256 dBodySetPosition (body
[1],0.5*LENGTH
,0,STARTZ
-HEIGHT
*0.5);
257 dBodySetPosition (body
[2],-0.5*LENGTH
, WIDTH
*0.5,STARTZ
-HEIGHT
*0.5);
258 dBodySetPosition (body
[3],-0.5*LENGTH
,-WIDTH
*0.5,STARTZ
-HEIGHT
*0.5);
262 joint[0] = dJointCreateHinge2 (world,0);
263 dJointAttach (joint[0],body[0],body[1]);
264 const dReal *a = dBodyGetPosition (body[1]);
265 dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]);
266 dJointSetHinge2Axis1 (joint[0],0,0,1);
267 dJointSetHinge2Axis2 (joint[0],0,1,0);
270 // front and back wheel hinges
271 for (i
=0; i
<3; i
++) {
272 joint
[i
] = dJointCreateHinge2 (world
,0);
273 dJointAttach (joint
[i
],body
[0],body
[i
+1]);
274 const dReal
*a
= dBodyGetPosition (body
[i
+1]);
275 dJointSetHinge2Anchor (joint
[i
],a
[0],a
[1],a
[2]);
276 dJointSetHinge2Axis1 (joint
[i
],0,0,1);
277 dJointSetHinge2Axis2 (joint
[i
],0,1,0);
280 // set joint suspension
281 for (i
=0; i
<3; i
++) {
282 dJointSetHinge2Param (joint
[i
],dParamSuspensionERP
,0.4);
283 dJointSetHinge2Param (joint
[i
],dParamSuspensionCFM
,0.8);
286 // lock back wheels along the steering axis
287 for (i
=1; i
<3; i
++) {
288 // set stops to make sure wheels always stay in alignment
289 dJointSetHinge2Param (joint
[i
],dParamLoStop
,0);
290 dJointSetHinge2Param (joint
[i
],dParamHiStop
,0);
291 // the following alternative method is no good as the wheels may get out
293 // dJointSetHinge2Param (joint[i],dParamVel,0);
294 // dJointSetHinge2Param (joint[i],dParamFMax,dInfinity);
297 // create car space and add it to the top level space
298 car_space
= dSimpleSpaceCreate (space
);
299 dSpaceSetCleanup (car_space
,0);
300 dSpaceAdd (car_space
,box
[0]);
301 dSpaceAdd (car_space
,sphere
[0]);
302 dSpaceAdd (car_space
,sphere
[1]);
303 dSpaceAdd (car_space
,sphere
[2]);
306 ground_box
= dCreateBox (space
,2,1.5,1);
308 dRFromAxisAndAngle (R
,0,1,0,-0.15);
309 dGeomSetPosition (ground_box
,2,0,-0.34);
310 dGeomSetRotation (ground_box
,R
);
313 dsSimulationLoop (argc
,argv
,352,288,&fn
);
315 dGeomDestroy (box
[0]);
316 dGeomDestroy (sphere
[0]);
317 dGeomDestroy (sphere
[1]);
318 dGeomDestroy (sphere
[2]);
319 dJointGroupDestroy (contactgroup
);
320 dSpaceDestroy (space
);
321 dWorldDestroy (world
);