Advertisement

Pogo stick physics ... again

Started by July 04, 2004 03:33 AM
22 comments, last by Luke Miklos 20 years, 4 months ago
I hate to bring up such an old topic, but I'm still tackling one last problem with my pogo stick game. Luke Miklos, if you're out there and have a moment of free time, please advise me on what to do. Okay, so I've got the pogo stick, I can find all the forces affecting it's motion, such as gravity, it's spring, and the force the surface applies to it on contact. I'm getting strange behaviour when the pogo stick collides with the ground. Sometimes it bounces only a very small amount, and sometimes it bounces an enormous amount. I believe the source of the trouble to be the "surface force", but it would be nice to have a second, and definitely more knowledgeable, opinion. In order to find the force that the surface of the terrain applies to the pogo stick on contact, I'm basing the calculations on my assumption that the force of the terrain is equal and opposite to the force the pogo stick applies to it, both by falling and bouncing. Is this assumption correct? Also, I've noticed that my gravity seems to be a little off, i.e. slightly less. I'm using SI units for all my values, -9.8 m/s/s gravity, ~68 kg's mass, a spring constant of 25,000 (i can't remember the units off hand), so is there any reason the simulation should be off?
"Donkey, if it were me, you'd be dead."I cna ytpe 300 wrods pre mniute.
im thinking if you have time code in your program that could be an issue. its not getting an accurate reading of the spring's compression. play around with it by maybe uping the number of samples per second.
Advertisement
hey man :)
hahaha, first of all, there probably many people on this forum who are much more knowledgable than me about phsyics... don't give me undue credit. ;) but I'll try to help now if I can.

Its good to see you're still hacking away at it, I hoped you would. Right now, I can't determine if you have a simple programming error (like forgetting to reset variables after they are consumed or used) or whether its a highlevel physics algorithm error. Lets start with physics (I'd still like to see some source, either here or email me) & lets just treat this system as a three part system...

part1) a massless (negligible) spring/pogostick that pushes with an equal force in both directions when its compressed.

part2) a free moving body that has mass, velocity, & thus momentum (or kinetic energy).

part3) the ground, perhaps not flat, but always pushes back on the pogostick with an equal force that is normal to the surface angle.

So here is how these 3 parts interact with each other:

At anygiven moment, the body has forces acting on it, gravity, a change in center of mass (the guy crunching down or straightening out), & the pogostick. I think we can just use these 3, so already... sounds simple right? well it is :)
(we'll discuss the change in center mass later, because I think I totally bastardized the concept & confused you last time) The spring is pushed on from both sides (when touching the ground) and stores energy within itself. It pushes on both the ground & the body equally. The force with which it pushes depends on its compression.

I think we both understand what forces are in action here & how to calculate them (cept maybe the one of the body from it's change in center of mass). Perhaps there are issue with how you update the position of all the entities... when the body moves, the spring/pogostick also moves... however, when the body changes its center of mass in mid air, the pogostick also moves with that center of mass. So if I was coding it, I would clamp the pogostick to the center of mass of the body, I would sum up the forces acting on the body each frame (in small iterations), update the position of the body each frame (in small iterations), which in turn updates the forces acting upon it (most importantly the spring's force) each frame (in small iterations). that is all there is to it man, without seeing some code, I can't go further. lemme know.

Luke





Whatsoever you do, do it heartily as to the Lord, and not unto men.
one thing I forgot to touch on...

from the view of the body, try & treat the spring as a "black box" with 1 input & 1 output. The spring's position (& hence compression) is inputed into the "black box" from the body as the body's position is updated. The springs force is supplied to the system as an output. Thats all the body should know... that it gives a position & receives a force, each iteration, each frame. good luck

Whatsoever you do, do it heartily as to the Lord, and not unto men.
Luke, you are the man. I'm considering the pogo-stick and the guy as one "system", where the mass and the pogo stick are "glued" together. Here's the code, with comments:

keyboard();	float small_amount_of_time = elapsed_time / 5;         //I'm sorry, but the variable name was too good not to use. 	for(float i = 0; i < elapsed_time; i += small_amount_of_time)	{		gravity_force.y = MASS * GRAVITY;// gravity                I know I should calculate it as a const , but that's later		vector a = velocity;                //velocity is a vector, and is the vector of the pogo's movement		vector b = transformation(1, spun_x, spun_y);                // b is the direction that the guy wants to go, lean forward, back, etc.		vector c(0, 0, 0);                // c will be used later for the surface normal		//this tests for a collision between the bottom of the pogo stick and the groundif(collision_model->collision(test_collision_model)) 		{			printf("Collision!\n");			int dummy; //no purpose, just placeholder, unimportant			collision_model->getCollidingTriangles(dummy, world_normal_index);// this finds which triangle of the ground the poogo stick hit			world_normal.x = world.surface_normal[world_normal_index].x;			world_normal.y = world.surface_normal[world_normal_index].y;			world_normal.z = world.surface_normal[world_normal_index].z;			world_normal.normalize();		}		else		{			world_normal.x = 0;			world_normal.y = 0;			world_normal.z = 0;			world_normal.magnitude = 0;		}		c = world_normal;// see, c again!		a.normalize();		b.normalize();		//c.normalize();                //c is already normalized because my format for the map saves 'em that way		float spring_compression_ratio = (a.x * b.x * c.x) + (a.y * b.y * c.y) + (a.z * b.z * c.z);                //this says how much the spring will compress, basically guy's direction, surface normal, and his velocity		if(spring_compression_ratio != 0)		{			printf("spring_compression_ratio %f \n", spring_compression_ratio);		}		if(spring_compression_ratio < 0)		{			spring_compression_ratio = fabs(spring_compression_ratio);		}		else		{			spring_compression_ratio = 0;		}                // this says that if the spring hit on the wrong end, i.e. top, ignore it		float spring_compression = spring_compression_ratio * heading.magnitude;		spring_force.x = b.x * SPRING_CONSTANT * spring_compression;		spring_force.y = b.y * SPRING_CONSTANT * spring_compression;		spring_force.z = b.z * SPRING_CONSTANT * spring_compression;		spring_force.find_magnitude();                //this is the force the spring exerts on the ground		surface_force.x = -(c.x * net_force.x);		surface_force.y = -(c.y * net_force.y);		surface_force.z = -(c.z * net_force.z);		surface_force.find_magnitude();                //this is where I'm confused. How do I calculate the final force the surface exerts back?		net_force.x = spring_force.x + surface_force.x + gravity_force.x;		net_force.y = spring_force.y + surface_force.y + gravity_force.y;		net_force.z = spring_force.z + surface_force.z + gravity_force.z;		net_force.find_magnitude();		//vector A;		acceleration.x = net_force.x / MASS;		acceleration.y = net_force.y / MASS;		acceleration.z = net_force.z / MASS;		acceleration.find_magnitude();		heading.x += acceleration.x * i;		heading.y += acceleration.y * i;		heading.z += acceleration.z * i;		heading.find_magnitude();		position.x += heading.x * i;		position.y += heading.y * i;		position.z += heading.z * i;		glPushMatrix();			glTranslatef(position.x, position.y, position.z);			glRotatef(spun_y, 0.0, 1.0, 0.0);			glRotatef(spun_x, 1.0, 0.0, 0.0);			glGetFloatv(GL_MODELVIEW_MATRIX, collision_model_matrix);			collision_model->setTransform(collision_model_matrix);		glPopMatrix();	}


Hopefully you can understand that. Am I doing the right thing by considering the spring and guy to be stuck together, just for now? Later I'll add his movements, but I need to make sure the basics work right.

edit: I just took a look at my code, and operator overloading would really help!
"Donkey, if it were me, you'd be dead."I cna ytpe 300 wrods pre mniute.
Duncan-BoJackson ;) ,

I've been up all night, I'll take a look at this tomorrow sometime afternoon. If by then... none of the other cool guys on the site have helped you out... I'll be there man :)

Luke
Advertisement
hey man,

Its obvious from looking at your code that you do not have the spring-mass model set up correctly. I will "tweak" it some & get something back to you sooner or later... after I find my physics book (so far everything has been from memory). Until then, maybe you could pass the time by working on the center of gravity change (as the guy bends his legs & straigtens them), perhaps optimize the physics model some (don't have local variables declared & initialized inside of loops, don't do a multiplication every frame when the value never changes... use const values) & perhaps even change the number of physics iterations you do each frame (try 10 or more, because with floating point rounding errors, sometimes your loop will run 5 times & sometimes it will run 4 times) so instead of using floats as the loop counters... use ints :)

Luke


Whatsoever you do, do it heartily as to the Lord, and not unto men.
I'm glad you were able to tell that from looking at my code :) Alright, I'll work on it some. I noticed, though, that when I change the amount of iterations, the "speed" of the game changes. I'm not sure why, I've looked at the code again and again, and unless my physics are wrong, well, I mean where they are wrong, :) , then it shouldn't change. But I'll go through everything. Thanks so much for helping out.
"Donkey, if it were me, you'd be dead."I cna ytpe 300 wrods pre mniute.
*sigh....
I also should have noticed that too...

For time independent physics with many iterations per frame, you have to do these things:

1) Calculate Elapsed_time since previous frame.

2) Iteration_time /*(small amount)*/ = elapsed time / num_iterations

3)
for (num_iterations){     //calculate net_force acting on mass   net_force = gravity + pogoForce //for now   acceleration = net_force / mass   //THIS IMPORTANT:   temp = acceleration * Iteration_time   //that gives you change in velocity, so...   velocity += temp   //THIS IMPORTANT:   temp = velocity * Iteration_time   //that gives you change in position, so...   position += temp}


Whatsoever you do, do it heartily as to the Lord, and not unto men.
not physics related, but one more thing...

I'm trying to picture somebody on a pogo-stick traversing some ground...

To make it look real, the stick has to be at an angle upon leaving the ground... (force from stick is applied along the stick) , but on the FLIP-SIDE... when the guy lands... the angle of the stick has changed, the guy doesn't keep the stick like this:
    O     -|- /   / \/    --->  -->     /    /   

as he bounces... he would fall on his face. the stick rotates around his center of mass to face at the same angle just in the opposite direction (relative to straight down).

So one thing to implement... is a stick rotating method... that will rotate the stick to land... & will do it a normal speed. ALl this can be calculated instantly upon leaving the ground (rather easily if you assume a flat ground, but still manageable if not). All you need to calculate is the speed of rotation, so something like this:

float CalculatRotationSpeed(void){   //all angles relative to the negative Y-axis   //assuming a 2-dimensional plane (projectile motion)   //with X-axis: forward  &  Y-axis: straight down   Target_Angle = -Current_Angle   velocity_Y = velocityMagnitude * sin(Current_Angle)   time_in_air = 2.0 * velocity_Y / 9.80146   angle_to_traverse = 2*Current_Angle   rotation_speed = angle_to_traverse / time_in_air }


so you have your rotation speed, so during your loop:

bool FlyingFlag;if(collision_model->collision(test_collision_model)) {   FlyingFlag = false;   ...   //other stuff.} else {   if(FlyingFlag) {      FlyingFlag = false;      CaculateRotationSpeed();   }...  //other stuff.}


& during your loop, somewhere (maybe at the bottom)

stick_angle += rotationSpeed * Elapsed_Time; //total frame time

Whatsoever you do, do it heartily as to the Lord, and not unto men.

This topic is closed to new replies.

Advertisement