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 *************************************************************************/
23 // Test for breaking joints, by Bram Stolk
25 #include <ode/odeconfig.h>
31 #include <drawstuff/drawstuff.h>
32 #include "texturepath.h"
36 #pragma warning(disable:4244 4305) // for VC++, no precision loss complaints
40 #define dsDrawBox dsDrawBoxD
41 #define dsDrawCylinder dsDrawCylinderD
45 // dynamics and collision objects (chassis, 3 wheels, environment)
47 static dWorldID world
;
48 static dSpaceID space
;
50 static const int STACKCNT
=10; // nr of weights on bridge
51 static const int SEGMCNT
=16; // nr of segments in bridge
52 static const float SEGMDIM
[3] = { 0.9, 4, 0.1 };
54 static dGeomID groundgeom
;
55 static dBodyID segbodies
[SEGMCNT
];
56 static dGeomID seggeoms
[SEGMCNT
];
57 static dBodyID stackbodies
[STACKCNT
];
58 static dGeomID stackgeoms
[STACKCNT
];
59 static dJointID hinges
[SEGMCNT
-1];
60 static dJointID sliders
[2];
61 static dJointFeedback jfeedbacks
[SEGMCNT
-1];
62 static dReal colours
[SEGMCNT
];
63 static int stress
[SEGMCNT
-1];
65 static dJointGroupID contactgroup
;
68 // this is called by dSpaceCollide when two objects in space are
69 // potentially colliding.
71 static void nearCallback (void *data
, dGeomID o1
, dGeomID o2
)
76 if (dGeomIsSpace(o1
) || dGeomIsSpace(o2
))
78 fprintf(stderr
,"testing space %p %p\n", o1
,o2
);
79 // colliding a space with something
80 dSpaceCollide2(o1
,o2
,data
,&nearCallback
);
81 // Note we do not want to test intersections within a space,
82 // only between spaces.
88 int n
= dCollide (o1
,o2
,N
,&(contact
[0].geom
),sizeof(dContact
));
91 for (int i
=0; i
<n
; i
++)
93 contact
[i
].surface
.mode
= dContactSoftERP
| dContactSoftCFM
| dContactApprox1
;
94 contact
[i
].surface
.mu
= 100.0;
95 contact
[i
].surface
.soft_erp
= 0.96;
96 contact
[i
].surface
.soft_cfm
= 0.02;
97 dJointID c
= dJointCreateContact (world
,contactgroup
,&contact
[i
]);
99 dGeomGetBody(contact
[i
].geom
.g1
),
100 dGeomGetBody(contact
[i
].geom
.g2
));
106 // start simulation - set viewpoint
110 dAllocateODEDataForThread(dAllocateMaskAll
);
112 static float xyz
[3] = { -6, 8, 6};
113 static float hpr
[3] = { -65.0f
, -27.0f
, 0.0f
};
114 dsSetViewpoint (xyz
,hpr
);
119 // called when a key pressed
121 static void command (int cmd
)
127 void drawGeom (dGeomID g
)
129 const dReal
*pos
= dGeomGetPosition(g
);
130 const dReal
*R
= dGeomGetRotation(g
);
132 int type
= dGeomGetClass (g
);
133 if (type
== dBoxClass
)
136 dGeomBoxGetLengths (g
, sides
);
137 dsDrawBox (pos
,R
,sides
);
139 if (type
== dCylinderClass
)
142 dGeomCylinderGetParams(g
, &r
, &l
);
143 dsDrawCylinder (pos
, R
, l
, r
);
148 static void inspectJoints(void)
150 const dReal forcelimit
= 2000.0;
152 for (i
=0; i
<SEGMCNT
-1; i
++)
154 if (dJointGetBody(hinges
[i
], 0))
156 // This joint has not snapped already... inspect it.
157 dReal l0
= dLENGTH(jfeedbacks
[i
].f1
);
158 dReal l1
= dLENGTH(jfeedbacks
[i
].f2
);
159 colours
[i
+0] = 0.95*colours
[i
+0] + 0.05 * l0
/forcelimit
;
160 colours
[i
+1] = 0.95*colours
[i
+1] + 0.05 * l1
/forcelimit
;
161 if (l0
> forcelimit
|| l1
> forcelimit
)
167 // Low-pass filter the noisy feedback data.
168 // Only after 4 consecutive timesteps with excessive load, snap.
169 fprintf(stderr
,"SNAP! (that was the sound of joint %d breaking)\n", i
);
170 dJointAttach (hinges
[i
], 0, 0);
179 static void simLoop (int pause
)
183 double simstep
= 0.002; // 2ms simulation steps
184 double dt
= dsElapsedTime();
185 int nrofsteps
= (int) ceilf(dt
/simstep
);
186 for (i
=0; i
<nrofsteps
&& !pause
; i
++)
188 dSpaceCollide (space
,0,&nearCallback
);
189 dWorldQuickStep (world
, simstep
);
190 dJointGroupEmpty (contactgroup
);
194 for (i
=0; i
<SEGMCNT
; i
++)
197 float v
= colours
[i
];
210 drawGeom(seggeoms
[i
]);
213 for (i
=0; i
<STACKCNT
; i
++)
214 drawGeom(stackgeoms
[i
]);
219 int main (int argc
, char **argv
)
223 // setup pointers to drawstuff callback functions
225 fn
.version
= DS_VERSION
;
228 fn
.command
= &command
;
230 fn
.path_to_textures
= DRAWSTUFF_TEXTURE_PATH
;
234 world
= dWorldCreate();
235 space
= dHashSpaceCreate (0);
236 contactgroup
= dJointGroupCreate (0);
237 dWorldSetGravity (world
,0,0,-9.8);
238 dWorldSetQuickStepNumIterations (world
, 20);
241 for (i
=0; i
<SEGMCNT
; i
++)
243 segbodies
[i
] = dBodyCreate (world
);
244 dBodySetPosition(segbodies
[i
], i
- SEGMCNT
/2.0, 0, 5);
245 dMassSetBox (&m
, 1, SEGMDIM
[0], SEGMDIM
[1], SEGMDIM
[2]);
246 dBodySetMass (segbodies
[i
], &m
);
247 seggeoms
[i
] = dCreateBox (0, SEGMDIM
[0], SEGMDIM
[1], SEGMDIM
[2]);
248 dGeomSetBody (seggeoms
[i
], segbodies
[i
]);
249 dSpaceAdd (space
, seggeoms
[i
]);
252 for (i
=0; i
<SEGMCNT
-1; i
++)
254 hinges
[i
] = dJointCreateHinge (world
,0);
255 dJointAttach (hinges
[i
], segbodies
[i
],segbodies
[i
+1]);
256 dJointSetHingeAnchor (hinges
[i
], i
+ 0.5 - SEGMCNT
/2.0, 0, 5);
257 dJointSetHingeAxis (hinges
[i
], 0,1,0);
258 dJointSetHingeParam (hinges
[i
],dParamFMax
, 8000.0);
260 // Here we tell ODE where to put the feedback on the forces for this hinge
261 dJointSetFeedback (hinges
[i
], jfeedbacks
+i
);
265 for (i
=0; i
<STACKCNT
; i
++)
267 stackbodies
[i
] = dBodyCreate(world
);
268 dMassSetBox (&m
, 2.0, 2, 2, 0.6);
269 dBodySetMass(stackbodies
[i
],&m
);
271 stackgeoms
[i
] = dCreateBox(0, 2, 2, 0.6);
272 dGeomSetBody(stackgeoms
[i
], stackbodies
[i
]);
273 dBodySetPosition(stackbodies
[i
], 0,0,8+2*i
);
274 dSpaceAdd(space
, stackgeoms
[i
]);
277 sliders
[0] = dJointCreateSlider (world
,0);
278 dJointAttach(sliders
[0], segbodies
[0], 0);
279 dJointSetSliderAxis (sliders
[0], 1,0,0);
280 dJointSetSliderParam (sliders
[0],dParamFMax
, 4000.0);
281 dJointSetSliderParam (sliders
[0],dParamLoStop
, 0.0);
282 dJointSetSliderParam (sliders
[0],dParamHiStop
, 0.2);
284 sliders
[1] = dJointCreateSlider (world
,0);
285 dJointAttach(sliders
[1], segbodies
[SEGMCNT
-1], 0);
286 dJointSetSliderAxis (sliders
[1], 1,0,0);
287 dJointSetSliderParam (sliders
[1],dParamFMax
, 4000.0);
288 dJointSetSliderParam (sliders
[1],dParamLoStop
, 0.0);
289 dJointSetSliderParam (sliders
[1],dParamHiStop
, -0.2);
291 groundgeom
= dCreatePlane(space
, 0,0,1,0);
293 for (i
=0; i
<SEGMCNT
; i
++)
297 dsSimulationLoop (argc
,argv
,352,288,&fn
);
299 dJointGroupEmpty (contactgroup
);
300 dJointGroupDestroy (contactgroup
);
302 // First destroy seggeoms, then space, then the world.
303 for (i
=0; i
<SEGMCNT
; i
++)
304 dGeomDestroy (seggeoms
[i
]);
305 for (i
=0; i
<STACKCNT
; i
++)
306 dGeomDestroy (stackgeoms
[i
]);
308 dSpaceDestroy(space
);
309 dWorldDestroy (world
);