Sign in to follow this  

ODE bouncing problem - wrong direction

This topic is 2517 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi everyone. I'm trying to integrate ODE into a project of mine due to its seemingly ease of use, but I've run into a roadblock that I've spent the past couple days trying to figure out. To that end, I'm hoping someone can help me.

I'm trying to do a simple object bounce off a ground plane. The problem I'm encountering is that, when an object collides with the ground plane, the y-component of its velocity is not what is being adjusted (despite the normal vector of the collision being (0,1,0) ). Instead, the z-component is adjusted, causing the object to shoot off in the -z direction once underground, while still falling according to gravity (parabolic motion).

I've scoured the web for as many tutorials as I could find, and searched to my best efforts through these forums for any info, but have not found anything similar to this problem.

So, does anyone know why it might be changing the z-component instead of the y-component of the object's velocity? Any help would be greatly appreciated as this has been driving me a tad crazy. Thanks!


void initODE()
{
World = dWorldCreate();
MAX_CONTACTS=20;
Space = dSimpleSpaceCreate(0);

contactgroup = dJointGroupCreate(0);

dCreatePlane(Space, 0, 1, 0, 0);

dWorldSetGravity(World, 0, -9.8, 0);

dWorldSetERP(World, 0.2);
dWorldSetCFM(World, 1e-5);

dWorldSetContactMaxCorrectingVel(World, 0.9);

dWorldSetContactSurfaceLayer(World, 0.001);

dWorldSetAutoDisableFlag(World, 0);
}

void worldObject::addToWorld()
{
dMatrix3 R, R1,R2,R3,R4;
float DEGTORAD=3.1415/180.0;

Body = dBodyCreate(World);

dBodySetPosition(Body, pos.x, pos.y, pos.z);

dBodySetLinearVel(Body, 0,0,0);

switch (type)
{
case (RECTANGLE):
{
dMassSetBox(&Mass, 1,width, height, length);
Geom = dCreateBox(Space, width, height, length);
break;
}
case (SPHERE):
{
dMassSetSphere(&Mass, 1, radius);
Geom = dCreateSphere(Space, radius);
break;
}
case (CYLINDER):
{
dMassSetCylinder(&Mass, 1, 1, radius1, length_cyl);
// Geom = dCreateCCylinder(Space, radius1, length_cyl);
break;
}
}
dBodySetMass(Body, &Mass);
dGeomSetBody(Geom, Body);
// Get the rotation from the editing and apply it
dRFromAxisAndAngle(R1,0,0,1,chi*DEGTORAD);
dRFromAxisAndAngle(R2,0,1,0,phi*DEGTORAD);
dRFromAxisAndAngle(R3,1,0,0,theta*DEGTORAD);
dMULTIPLY0_333(R4,R1,R2);
dMULTIPLY0_333(R,R4,R3);
dBodySetRotation(Body, R);
}


static void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
int i;
dBodyID b1 = dGeomGetBody(o1);
dBodyID b2 = dGeomGetBody(o2);
dContact contact[MAX_CONTACTS];

for (i = 0; i < MAX_CONTACTS; i++)
{
contact[i].surface.mode = dContactBounce | dContactSoftCFM;
contact[i].surface.mu = dInfinity;
contact[i].surface.mu2 = 0;
contact[i].surface.bounce = 0.51;
contact[i].surface.bounce_vel = 0.1;
contact[i].surface.soft_cfm = 1.01;
}

if (int numc = dCollide(o1, o2, MAX_CONTACTS, &contact[0].geom, sizeof(dContact)))
{
for (i = 0; i < numc; i++)
{
dJointID c = dJointCreateContact(World, contactgroup, &contact[i]);
dJointAttach(c, b1, b2);
}
}
}

void collide()
{
dSpaceCollide(Space, 0, &nearCallback);
dWorldQuickStep(World, gameTime);
dJointGroupEmpty(contactgroup);
}


Share this post


Link to post
Share on other sites
Thanks; the relevant function is included in the code above. It's copied near directly from a tutorial (which works) save for variable names. This has me baffled. Is there anyone with any ODE experience that can see what I'm missing?

Thanks

Share this post


Link to post
Share on other sites
Hi. I have about 4 hours ODE experience.

From what I understand from ODE, there is a simple unison of geometries and actual bodies in 3d space; the geometries possessing the physics attributes
while the actual bodies that the programmer binds to geometries, inherit features from these preset characteristics. It is this which allows for easy and pain free usage.
ODE is essentially "paste geometry to actual object library".

So, it is very important that you have unique geometries for each actual body type for example. Maybe when I have more than a day of ODE experience, I can validate my initial understanding.


I was able to scratch code a simple little demonstration of ODE in action. And i mean as minimal action as possible. Just fall and bounce. I jsut wanted to test how
quickly I could create a gl+ode app, and it was also good practice.

[url="http://www.youtube.com/watch?v=ZiM_rD6EbcM"]ode test[/url]

Share this post


Link to post
Share on other sites
This is my exact code ( well the ode section )

[quote]
// :----: global ode variables
#define geometries_per_body 1
#define maximum_colission_joints 4 // :----: a cube will have 4 joints in a colission instance
#define geometry_density 0.5
MATRIX geometry_matrix;
struct my_object
{
dBodyID cube_body;
dGeomID cube_geometry [ geometries_per_body ];
};
my_object cube_solid;
dWorldID environment;
dSpaceID continuom;
dJointGroupID colission_joints;
GLuint cube_solid_y_pos = 10;
[/quote]

I love object oriented programming, so almost anithing i do is objected oriented, from python to c. If you want to use it, just take out the "program::" bit

[quote]
bool program::initiate_ode ( )
{
// :----: world setup
environment = dWorldCreate ( );
continuom = dSimpleSpaceCreate ( 0 );
colission_joints = dJointGroupCreate ( 0 );
dCreatePlane ( continuom, 0, 1, 0, 0 );
dWorldSetGravity ( environment, 0, -1.0, 0 );
dWorldSetERP ( environment, 0.2 );
dWorldSetCFM ( environment, 1e-5 );
dWorldSetContactMaxCorrectingVel ( environment, 0.9 );
dWorldSetContactSurfaceLayer ( environment, 0.001 );
dWorldSetAutoDisableFlag ( environment, 1 );
// :----: object setup vars
dMatrix3 geometry_rotation;
VECTOR geometry_temp_vector ( 0.0, 0.0, 0.0 );
size_t geometry_data = 0;
dMass geometry_mass;
dReal geometry_sides [ 3 ];
geometry_sides [ 0 ] = 2.0, geometry_sides [ 1 ] = 2.0, geometry_sides [ 2 ] = 2.0;
// :----: object setup
cube_solid.cube_body = dBodyCreate ( environment );
dBodySetPosition ( cube_solid.cube_body, -1.5, cube_solid_y_pos, 3 );

dRFromAxisAndAngle ( geometry_rotation, dRandReal ( ) * 2.0 - 1.0, dRandReal ( ) * 2.0 - 1.0, dRandReal ( ) * 2.0 - 1.0, dRandReal ( ) * 10.0 - 5.0 );
dBodySetRotation ( cube_solid.cube_body, geometry_rotation );

dBodySetLinearVel ( cube_solid.cube_body, geometry_temp_vector.x, geometry_temp_vector.y, geometry_temp_vector.z );

dBodySetData ( cube_solid.cube_body, ( void * ) geometry_data );

dMassSetBox ( &geometry_mass, geometry_density, geometry_sides [ 0 ], geometry_sides [ 1 ], geometry_sides [ 2 ] );
dBodySetMass ( cube_solid.cube_body, &geometry_mass );

cube_solid.cube_geometry [ 0 ] = dCreateBox ( continuom, geometry_sides [ 0 ], geometry_sides [ 1 ], geometry_sides [ 2 ] );
dGeomSetBody ( cube_solid.cube_geometry [ 0 ], cube_solid.cube_body );
}

bool program::de_initiate_ode ( )
{
dWorldDestroy ( environment );
dSpaceDestroy ( continuom );
dJointGroupDestroy ( colission_joints );
}

static void ode_callback ( void *geometry_data, dGeomID geometry_zero, dGeomID geometry_one )
{
int ode_index;
dBodyID _geometry_zero = dGeomGetBody ( geometry_zero );
dBodyID _geometry_one = dGeomGetBody ( geometry_one );
dContact colission_contact [ maximum_colission_joints ];

for ( ode_index = 0; ode_index < maximum_colission_joints; ode_index ++ )
{
colission_contact [ ode_index ].surface.mode = dContactBounce | dContactSoftCFM;
colission_contact [ ode_index ].surface.mu = dInfinity;
colission_contact [ ode_index ].surface.mu2 = 0;
colission_contact [ ode_index ].surface.bounce = 0.01;
colission_contact [ ode_index ].surface.bounce_vel = 0.1;
colission_contact [ ode_index ].surface.soft_cfm = 0.01;
}

if ( int ode_cardinality = dCollide ( geometry_zero, geometry_one, maximum_colission_joints, &colission_contact [ 0 ].geom, sizeof ( dContact ) ) )
{
for ( ode_index = 0; ode_index < ode_cardinality; ode_index ++ )
{
dJointID ode_joint_id = dJointCreateContact ( environment, colission_joints, colission_contact + ode_index );
dJointAttach ( ode_joint_id, _geometry_zero, _geometry_one );
}
}
}

bool program::ode_cycle ( )
{
dSpaceCollide ( continuom, 0, &ode_callback );
dWorldQuickStep ( environment, 0.05 );
dJointGroupEmpty ( colission_joints );
program ( ).project_geometry ( cube_solid.cube_geometry [ 0 ], 0, 0, 0 );
}

// draws geometry
void program::project_geometry ( dGeomID geometry_body, const dReal *geometry_position, const dReal *geometry_rotation, int project_ode )
{
if ( !geometry_body ) return;
if ( !geometry_position ) geometry_position = dGeomGetPosition ( geometry_body );
if ( !geometry_rotation ) geometry_rotation = dGeomGetRotation ( geometry_body );
int geometry_type = dGeomGetClass ( geometry_body );
if ( geometry_type == dBoxClass )
{
dReal geometry_sides [ 3 ];
dGeomBoxGetLengths ( geometry_body, geometry_sides );
program ( ).project_actual_cube_solid ( geometry_sides, geometry_position, geometry_rotation );
}
}

//draws actual object
bool program::project_actual_cube_solid ( const dReal geometry_sides [ 3 ], const dReal geometry_position [ 3 ], const dReal geometry_rotation [ 12 ] )
{
glPushMatrix ( );
geometry_matrix.ode_to_gl ( geometry_position, geometry_rotation );
glMultMatrixf ( geometry_matrix.Element );
generate_image ( "data/images/cube solid texture.bmp" );
project_cube_solid ( ); // this is just a normal cube, drawn in the normal gl way
glPopMatrix ( );
}
[/quote]

ODE DONE!!!!

Dont't mind the "project ( ).method" bit. It's just another way of doing this:
//normal declaration
project run;
run.method ( )

//my shortcut
project ( ).method ( );


It's an accident i found out when i used to code SDL games....: )

Share this post


Link to post
Share on other sites
I then use this function to reset object's orientation at runtime.

[quote]
bool program::controls ( )
{
// :----: in addition to position, the cube's geometry rotation needs to also be reset, so it's different each fall
dMatrix3 geometry_rotation;

if ( ( key [ 'R' ] ) && ( pressingr == false ) )
{
pressingr = true;
dBodySetPosition ( cube_solid.cube_body, 0, cube_solid_y_pos, 0 );
dRFromAxisAndAngle ( geometry_rotation, dRandReal ( ) * 2.0 - 1.0, dRandReal ( ) * 2.0 - 1.0, dRandReal ( ) * 2.0 - 1.0, dRandReal ( ) * 10.0 - 5.0 );
dBodySetRotation ( cube_solid.cube_body, geometry_rotation );
}
else
{
pressingr = false;
}
}
[/quote]

Share this post


Link to post
Share on other sites

This topic is 2517 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this