Jump to content
  • Advertisement
Sign in to follow this  
Concentrate

Simulating pendulum movement

This topic is 3188 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

I know there is something wrong here. I am trying to simulate a simple pendulum by am failing. Here is the relevancy.
struct Pendulum
{
	RigidBall ball;
	Line rope;
	const int LEN;	
	
	float changeInAngle;
	const float restAngle;

	Pendulum() : LEN( 6 ), restAngle( Constants::DEGTORAD * 270 )
	{
		rope = Line( Vector3D( 0.0f,-LEN,0.0f) );	
		rope.setWhiteColor();
		ball = RigidBall(1,1,0.0f,-LEN,0.0f);
		ball.setYellowColor();
		ball.setMass( 1.0f );		

		changeInAngle = 75 * Constants::DEGTORAD;
		
		ball.posVec = Vector3D( LEN * cos( ( restAngle + changeInAngle ) ),
								LEN * sin( ( restAngle + changeInAngle ) ),
								0.0f);			
	}
	void calculate(float deltaTime)
	{
		static const float EXTRA_FORCE = 5;

		static float g = Constants::GRAVITY / LEN * EXTRA_FORCE;		
		//F = mg*sin(theta) = ma;
		//a = F/ m
		//a = mgsin(theta) / m	
		//a = g*sin(theta)
		ball.accelVec = Vector3D( 0.0f, g * sin( changeInAngle ) , 0.0f );

		//V = v_0 + a*t
		ball.velVec += ball.accelVec * deltaTime;

		// X = v*dt + 1/2 a*dt^2
		ball.posVec += ball.velVec * deltaTime;// + 1.0f/2.0f * ball.accelVec * deltaTime * deltaTime;
		
		changeInAngle = atan2( ball.posVec.getY(), ball.posVec.getX() ) - restAngle;
		
		rope.setEndPoint( ball.posVec );
	}
	void draw(float deltaTime)
	{
		calculate(deltaTime);
		rope.draw();	
		ball.draw();
		//draw axis
		glBegin(GL_LINES);
			glColor3f(1.0f,0.0f,0.0f);
			glVertex3f(-7.0f,0.0f,0.0f);
			glVertex3f(7.0f,0.0f,0.0f);
			glVertex3f(0.0f,-7.0f,0.0f);
			glVertex3f(0.0f,7.0f,0.0f);
		glEnd();
		
	}
}pendulum;



I know some logic is wrong. Can you help ? When I run it the pendulum does not oscillate towards the x = 0 line. It just decays down the y-axis. after a few millisecond. [Edited by - Concentrate on December 25, 2009 10:23:42 PM]

Share this post


Link to post
Share on other sites
Advertisement
I though my calculation was correct but apparently not.

Can someone check my calculation.

void calculate(float deltaTime)
{
static const float EXTRA_FORCE = 5;

static float g = Constants::GRAVITY / LEN * EXTRA_FORCE;
//F = mg*sin(theta) = ma;
//a = F/ m
//a = mgsin(theta) / m
//a = g*sin(theta)
ball.accelVec = Vector3D( g * sin( changeInAngle ) ,g * cos(changeInAngle) , 0.0f );

//V = v_0 + a*t
ball.velVec += ball.accelVec * deltaTime;


// X = v*dt + 1/2 a*dt^2
ball.posVec += ball.velVec * deltaTime;// + 1.0f/2.0f * ball.accelVec * deltaTime * deltaTime;

changeInAngle = atan2( ball.posVec.getY(), ball.posVec.getX() ) - restAngle;

rope.setEndPoint( ball.posVec );
}




restAngle is 270 degrees in radians.

Share this post


Link to post
Share on other sites
It appears that you're calculating the force on the ball based on a change in angle.

The force on the ball due to gravity will be a constant m*g in the vertical direction, whatever the position of the ball. The acceleration vector will be (0,-m*g,0), and the change in velocity accelVec*deltaSecs, if the Y axis is pointing up.

Share this post


Link to post
Share on other sites
>>It appears that you're calculating the force on the ball based on a change in angle.

Yes.

>>The force on the ball due to gravity will be a constant m*g in the vertical direction, whatever the position of the ball. The acceleration vector will be (0,-m*g,0), and the change in velocity accelVec*deltaSecs, if the Y axis is pointing up.

Thanks. How will I account, for the horizontal force then ?

Share this post


Link to post
Share on other sites
The horizontal force comes from the rope. You're probably simulating it as a straight rod (which is simplest).

Divide the vertical force (m*g*deltaSecs) into a force along the direction of the rope and a force normal to the rope, according to the angle the rope makes with the vertical. The force along the direction of the rope will be cancelled by the force of the rope on the ball. The normal force (perpendicular to the rope) will cause acceleration normal to the rope.

Share this post


Link to post
Share on other sites
Quote:
Original post by Buckeye
The horizontal force comes from the rope. You're probably simulating it as a straight rod (which is simplest).

Divide the vertical force (m*g*deltaSecs) into a force along the direction of the rope and a force normal to the rope, according to the angle the rope makes with the vertical. The force along the direction of the rope will be cancelled by the force of the rope on the ball. The normal force (perpendicular to the rope) will cause acceleration normal to the rope.



Is that tangential force
 mg*sin(theta)?

Share this post


Link to post
Share on other sites
If, by "tangential," you mean perpendicular to the direction of the rope, then yes. And if your "theta" is the angle of the rope with respect to the Y axis, Y pointing down, then that force would be m*g*sin(theta).

Make sure you apply the sign of the angle correctly - the force will always tend to swing the ball back toward that Y axis.

Share this post


Link to post
Share on other sites
Sorry for the late response.

I think my calculations are correct but the result shows otherwise. I am trying
what you said, but its acting weird.

This is what I have now :

void calculate(float deltaTime)
{
static const float EXTRA_FORCE = 10;

static float g = Constants::GRAVITY / LEN * EXTRA_FORCE;

//F = mg*sin(theta) = ma;
//a = F/ m
//a = mgsin(theta) / m
//a = g*sin(theta)
ball.forceVec = Vector3D( ball.getMass() * g * sin(changeInAngle) , ball.getMass() * g , 0.0f);

ball.accelVec = ball.forceVec/ ball.getMass();

//V = v_0 + a*t
ball.velVec += ball.accelVec * deltaTime;


// X = v*dt + 1/2 a*dt^2
ball.posVec += ball.velVec * deltaTime + 1.0f/2.0f * ball.accelVec * deltaTime * deltaTime;


changeInAngle = atan2( ball.posVec.getY(), ball.posVec.getX() ) - restAngle;

rope.setEndPoint( ball.posVec );
}



Here is whats happening ,

Share this post


Link to post
Share on other sites
pendulum

Maybe this picture will help. In this picture, theta is the angle between the Y-axis and the rope.

mg points down along the Y-axis (always). The tangential force [mg sin(theta)] is not opposed and is what causes the acceleration. The force on the ball from the rope can only be along the direction of the rope and is always equal to mg*cos(theta).

Divide the rope force into x- and y-components (shown on the right):

x-force = -mg cos(theta) sin(theta)
y-force = -mg cos(theta) cos(theta)

At an angle theta, the force on the ball is:

Vector3D( -m*g*cos(theta)*sin(theta), m*g - (-m*g*cos(theta)*cos(theta)), 0);

The Y component = mg + (1-cos^2(theta)). 1-cos^2 = sin^2, so:

force = Vector3D( -m*g*cos(theta)*sin(theta), m*g*sin(theta)*sin(theta), 0);

Testing some values-

When the ball is hanging straight down, theta = 0 and force = (0,0,0). That is, there is no tangential force and the rope supports the ball. The velocity is not affected.

When the ball is straight out to the right, theta = pi/2 and force = (0, mg, 0). Gravity is pulling straight down on the ball and acceleration is maximum.


Share this post


Link to post
Share on other sites
Thanks for the explanation. Shouldn't the second triangle (the one on the right of your picture) be the same as the first one ( the one on the left of your picture) because I thought they should be similar triangles?

I must be doing something wrong because I adjusted the force from your derivation
and its similar to what I had in the youtube video (plus/minus).

This is what I have for the current definition,

struct Pendulum
{
RigidBall ball;
Line rope;
const int LEN;

float changeInAngle;
const float restAngle;

Pendulum() : LEN( 6 ), restAngle( Constants::DEGTORAD * 270 )
{
rope = Line( Vector3D( 0.0f,-LEN,0.0f) );
rope.setWhiteColor();
ball = RigidBall(1,1,0.0f,-LEN,0.0f);
ball.setYellowColor();
ball.setMass( 1.0f );

changeInAngle = 75 * Constants::DEGTORAD;

ball.posVec = Vector3D( LEN * cos( ( restAngle + changeInAngle ) ),
LEN * sin( ( restAngle + changeInAngle ) ),
0.0f);
}
void calculate(float deltaTime)
{
static const float EXTRA_FORCE = 10;

static float g = Constants::GRAVITY / LEN * EXTRA_FORCE;
static float m = ball.getMass();
float theta = changeInAngle;
//F = mg*sin(theta) = ma;
//a = F/ m
//a = mgsin(theta) / m
//a = g*sin(theta)
ball.forceVec = Vector3D( -m*g*cos(theta)*sin(theta), m*g*sin(theta)*sin(theta), 0);


ball.accelVec = ball.forceVec/ ball.getMass();

//V = v_0 + a*t
ball.velVec += ball.accelVec * deltaTime;


// X = v*dt + 1/2 a*dt^2
ball.posVec += ball.velVec * deltaTime + 1.0f/2.0f * ball.accelVec * deltaTime * deltaTime;


changeInAngle = atan2( ball.posVec.getY(), ball.posVec.getX() ) - restAngle;

rope.setEndPoint( ball.posVec );
}
void draw(float deltaTime)
{
calculate(deltaTime);
rope.draw();
ball.draw();

}
}pendulum;




I don't think its any problem with my display function because I do not
manipluate anything except the time in there.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!