Simulating pendulum movement

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

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 );

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 on other sites
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 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 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 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 on other sites
Quote:
 Original post by BuckeyeThe 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 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 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 on other sites

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 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 );

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.

1. 1
2. 2
Rutin
16
3. 3
4. 4
5. 5

• 26
• 11
• 9
• 9
• 11
• Forum Statistics

• Total Topics
633703
• Total Posts
3013453
×