mirror of
https://github.com/nasa/trick.git
synced 2025-02-23 10:10:21 +00:00
Added a 3 wheeled car example from the ODE demos. I collapsed all of the separate classes handling the world, objects, and drawings into a single class. Each world is different and just including that with the objects for these simple examples is easier. Same goes for the drawing. refs #172
218 lines
6.2 KiB
C++
218 lines
6.2 KiB
C++
|
|
#include <ode/ode.h>
|
|
#include <drawstuff/drawstuff.h>
|
|
|
|
#include "Buggy.hh"
|
|
#include "trick/memorymanager_c_intf.h"
|
|
|
|
Buggy::Buggy() :
|
|
gravity(-0.5),
|
|
chassis_length(0.7),
|
|
chassis_width(0.5),
|
|
chassis_height(0.2),
|
|
chassis_mass(1.0),
|
|
wheel_radius(.18),
|
|
wheel_width(0.02),
|
|
wheel_mass(0.2),
|
|
start_z(0.5)
|
|
{}
|
|
|
|
int Buggy::init() {
|
|
|
|
dMass m;
|
|
int i ;
|
|
|
|
dInitODE2(0);
|
|
world = dWorldCreate ();
|
|
space = dHashSpaceCreate (0);
|
|
contactgroup = dJointGroupCreate(0);
|
|
|
|
dWorldSetGravity (world,0,0,gravity);
|
|
|
|
ground = dCreatePlane (space,0,0,1,0);
|
|
|
|
// chassis body
|
|
body[0] = dBodyCreate (world);
|
|
dBodySetPosition (body[0],0,0,start_z);
|
|
dMassSetBox (&m,1,chassis_length,chassis_width,chassis_height);
|
|
dMassAdjust (&m,chassis_mass);
|
|
dBodySetMass (body[0],&m);
|
|
box[0] = dCreateBox (0,chassis_length,chassis_width,chassis_height);
|
|
dGeomSetBody (box[0],body[0]);
|
|
|
|
buggy_body_pos = (dReal *)dGeomGetPosition(box[0]) ;
|
|
TMM_declare_ext_var_1d( buggy_body_pos , "float" , 3) ;
|
|
|
|
// wheel bodies
|
|
for (i=1; i<=3; i++) {
|
|
body[i] = dBodyCreate (world);
|
|
dQuaternion q;
|
|
dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
|
|
dBodySetQuaternion (body[i],q);
|
|
dMassSetSphere (&m,1,wheel_radius);
|
|
dMassAdjust (&m,wheel_mass);
|
|
dBodySetMass (body[i],&m);
|
|
sphere[i-1] = dCreateSphere (0,wheel_radius);
|
|
dGeomSetBody (sphere[i-1],body[i]);
|
|
}
|
|
dBodySetPosition (body[1],0.5*chassis_length,0,start_z-chassis_height*0.5);
|
|
dBodySetPosition (body[2],-0.5*chassis_length, chassis_width*0.5,start_z-chassis_height*0.5);
|
|
dBodySetPosition (body[3],-0.5*chassis_length,-chassis_width*0.5,start_z-chassis_height*0.5);
|
|
|
|
// front and back wheel hinges
|
|
for (i=0; i<3; i++) {
|
|
joint[i] = dJointCreateHinge2 (world,0);
|
|
dJointAttach (joint[i],body[0],body[i+1]);
|
|
const dReal *a = dBodyGetPosition (body[i+1]);
|
|
dJointSetHinge2Anchor (joint[i],a[0],a[1],a[2]);
|
|
dJointSetHinge2Axis1 (joint[i],0,0,1);
|
|
dJointSetHinge2Axis2 (joint[i],0,1,0);
|
|
}
|
|
|
|
// set joint suspension
|
|
for (i=0; i<3; i++) {
|
|
dJointSetHinge2Param (joint[i],dParamSuspensionERP,0.4);
|
|
dJointSetHinge2Param (joint[i],dParamSuspensionCFM,0.8);
|
|
}
|
|
|
|
// lock back wheels along the steering axis
|
|
for (i=1; i<3; i++) {
|
|
// set stops to make sure wheels always stay in alignment
|
|
dJointSetHinge2Param (joint[i],dParamLoStop,0);
|
|
dJointSetHinge2Param (joint[i],dParamHiStop,0);
|
|
}
|
|
|
|
// create car space and add it to the top level space
|
|
car_space = dSimpleSpaceCreate (space);
|
|
dSpaceSetCleanup (car_space,0);
|
|
dSpaceAdd (car_space,box[0]);
|
|
dSpaceAdd (car_space,sphere[0]);
|
|
dSpaceAdd (car_space,sphere[1]);
|
|
dSpaceAdd (car_space,sphere[2]);
|
|
|
|
// environment
|
|
ground_box = dCreateBox (space,2,1.5,1);
|
|
dMatrix3 R;
|
|
dRFromAxisAndAngle (R,0,1,0,-0.15);
|
|
dGeomSetPosition (ground_box,2,0,-0.34);
|
|
dGeomSetRotation (ground_box,R);
|
|
|
|
// Add this object to DrawStuff
|
|
add_object() ;
|
|
return 0 ;
|
|
}
|
|
|
|
int Buggy::step(double time_step) {
|
|
dJointSetHinge2Param (joint[0],dParamVel2,-speed);
|
|
dJointSetHinge2Param (joint[0],dParamFMax2,0.1);
|
|
|
|
// steering
|
|
dReal v = steer - dJointGetHinge2Angle1 (joint[0]);
|
|
if (v > 0.1) v = 0.1;
|
|
if (v < -0.1) v = -0.1;
|
|
v *= 10.0;
|
|
dJointSetHinge2Param (joint[0],dParamVel,v);
|
|
dJointSetHinge2Param (joint[0],dParamFMax,0.2);
|
|
dJointSetHinge2Param (joint[0],dParamLoStop,-0.75);
|
|
dJointSetHinge2Param (joint[0],dParamHiStop,0.75);
|
|
dJointSetHinge2Param (joint[0],dParamFudgeFactor,0.1);
|
|
|
|
dSpaceCollide (space,this,&Buggy::nearCallback);
|
|
dWorldStep (world,time_step);
|
|
|
|
// remove all contact joints
|
|
dJointGroupEmpty (contactgroup);
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
int Buggy::shutdown() {
|
|
dGeomDestroy (box[0]);
|
|
dGeomDestroy (sphere[0]);
|
|
dGeomDestroy (sphere[1]);
|
|
dGeomDestroy (sphere[2]);
|
|
dJointGroupDestroy (contactgroup);
|
|
dSpaceDestroy (space);
|
|
dWorldDestroy (world);
|
|
dCloseODE();
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
int Buggy::draw() {
|
|
int i ;
|
|
|
|
dsSetColor (0,1,1);
|
|
dsSetTexture (DS_WOOD);
|
|
dReal sides[3] = {chassis_length,chassis_width,chassis_height};
|
|
dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides);
|
|
dsSetColor (1,1,1);
|
|
for (i=1; i<=3; i++) {
|
|
dsDrawCylinder (dBodyGetPosition(body[i]), dBodyGetRotation(body[i]),wheel_width,wheel_radius);
|
|
}
|
|
|
|
dVector3 ss;
|
|
dGeomBoxGetLengths (ground_box,ss);
|
|
dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss);
|
|
|
|
return 0 ;
|
|
}
|
|
|
|
void Buggy::command( int cmd ) {
|
|
switch (cmd) {
|
|
case 'a': case 'A':
|
|
speed += 0.3;
|
|
break;
|
|
case 'z': case 'Z':
|
|
speed -= 0.3;
|
|
break;
|
|
case ',':
|
|
steer -= 0.5;
|
|
break;
|
|
case '.':
|
|
steer += 0.5;
|
|
break;
|
|
case ' ':
|
|
speed = 0;
|
|
steer = 0;
|
|
break;
|
|
case '1': {
|
|
FILE *f = fopen ("state.dif","wt");
|
|
if (f) {
|
|
dWorldExportDIF (world,f,"");
|
|
fclose (f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// this is called by dSpaceCollide when two objects in space are
|
|
// potentially colliding.
|
|
void Buggy::nearCallback (void * void_buggy , dGeomID o1, dGeomID o2) {
|
|
|
|
int i,n;
|
|
Buggy * bp = (Buggy *)void_buggy ;
|
|
|
|
// only collide things with the ground
|
|
int g1 = (o1 == bp->ground || o1 == bp->ground_box);
|
|
int g2 = (o2 == bp->ground || o2 == bp->ground_box);
|
|
if (!(g1 ^ g2)) return;
|
|
|
|
const int N = 10;
|
|
dContact contact[N];
|
|
n = dCollide (o1,o2,N,&contact[0].geom,sizeof(dContact));
|
|
if (n > 0) {
|
|
for (i=0; i<n; i++) {
|
|
contact[i].surface.mode = dContactSlip1 | dContactSlip2 |
|
|
dContactSoftERP | dContactSoftCFM | dContactApprox1;
|
|
contact[i].surface.mu = dInfinity;
|
|
contact[i].surface.slip1 = 0.1;
|
|
contact[i].surface.slip2 = 0.1;
|
|
contact[i].surface.soft_erp = 0.5;
|
|
contact[i].surface.soft_cfm = 0.3;
|
|
dJointID c = dJointCreateContact (bp->world,bp->contactgroup,&contact[i]);
|
|
dJointAttach (c, dGeomGetBody(contact[i].geom.g1), dGeomGetBody(contact[i].geom.g2));
|
|
}
|
|
}
|
|
}
|