Why does my pendulum stop?

Title says it all.

``````using UnityEngine;

public class Ball : MonoBehaviour
{
public Vector2 position;
public Vector2 velocity;
public float gravity = -9.81f;
public float antiHingeForce = 1;

public float lastTurnDuration;
public float turnDuration;
public float change;

public float lastTurnTime;

bool turnWritten;

void Start()
{
position = transform.position;
}
private void FixedUpdate()
{
CountTurnTime();

Vector2 lastVelocity = velocity;

// gravity
Vector2 gravityVec = Vector2.up * Time.fixedDeltaTime * Time.fixedDeltaTime * gravity;

Vector2 velocityChange = Vector2.zero;

velocityChange += lastVelocity;
velocityChange += gravityVec;
// lastVelocity (momentum)
// drag

// all projected on circle
Vector2 normal = Vector2.Perpendicular(position);
Vector2 projected = Vector3.Project(velocityChange, normal);

velocity = projected;
position += projected;

transform.position = position;
}

void CountTurnTime()
{
if (transform.position.x > 0 && transform.position.y > 0 && !turnWritten)
{
turnWritten = true;

lastTurnDuration = turnDuration;
turnDuration = Time.time - lastTurnTime;

change = lastTurnDuration - turnDuration;

lastTurnTime = Time.time;
}
if (transform.position.x < 0)
{
turnWritten = false;
}
}
}
``````

Physics is a discrete simulation. Itâ€™s always gonna gain / lose energy through floating point inaccuracies and timing / sampling issues.

1 Like

Time shouldnâ€™t matter on a fixed timestep (FixedUpdate).

And it gets slower way too fast - after ~10 times going back and forth, it already loses about the height of the ball (~1 unit).

Which makes me think there is an error in my calculation.
The projection perhaps? Do I have to scale the resulting vector maybe? Idk.

Iâ€™ve a feeling mass is missing from your equations, though I donâ€™t know where it would go since my Newtonian physics is rather rusty.

Mass is famously irrelevant for the motion of a pendulum.

On the contrary. It matters quite a bit. Imagine the case of a ball simply falling from a fixed height to the ground. In real life, the ball accelerates continuously, with its position perfectly described by a parabola.

Now imagine a fixed-timestep simulation with the same gravity. During each fixed timestep (FixedUpdate), a new velocity is calculated. That velocity is then used for the entire next fixed timestep. There is no acceleration at all during the step. It isnâ€™t until the next step that all of the â€śaccumulatedâ€ť velocity is added that should have been added for the timestep. The result is:

• The ball falls somewhat slower than it should in a continuous simulation because acceleration gets delayed.
• The height of the projectile does not follow a smooth parabolic curve, but rather a sort of sharp-edged â€śparabola-ishâ€ť shape made of small line segments, each segment being a time step during which the ball moved at a constant velocity.

The smaller the timestep, the higher the â€śresolutionâ€ť of those straight line segments and the more it will look like a smooth parabola. Likewise, the smaller the timestep, the less error there will be when compared to a real â€ścontinuousâ€ť simulation.

But as long as itâ€™s a discrete simulation, there will be error related to that. This is in addition to floating point precision error by the way.

3 Likes

As Praetor notes, yes, it does matter. There are four main portions to your curve: left side, right side, and going up versus going down, those four combinations. The only time it would be stable is if the time slicing worked out so that the slices all happened precisely at the transitions between those states, and the integrated sum on each quadrant matched.

If you need SHM for something just use a sine function and drive a rotation with it, something like:

``````float angle = Mathf.Sin( Time.time * FrequencyFactor) * MaxDeflectionAngle;
``````

then use angle to make a rotation:

``````pendulumTransform.rotation = Quaternion.Euler (0, 0, angle);
``````

The same goes for orbital mechanics or indeed any physics. I remember in 10th grade high school when I learned the equations for orbits and hurried home to try them on my Vic-20 computer in BASIC, and I was so disappointed when I couldnâ€™t get them to stay stable: the planet always either sped up or slowed down over timeâ€¦ and in 11th grade I learned why when I took Calculus classes and learned about integration and how it applied to discrete simulations.

Fixed it

``````private void FixedUpdate()
{
CountTurnTime();

Vector2 lastVelocity = velocity;

Vector2 normal = Vector2.Perpendicular(position);

// gravity
Vector2 gravityVec = Vector2.up * Time.fixedDeltaTime * Time.fixedDeltaTime * gravity;
Vector2 gravityVec_Projected = Vector3.Project(gravityVec, normal);

// lastVelocity (momentum)
Vector2 lastVelocity_Projected = Vector3.Project(lastVelocity, normal);
lastVelocity_Projected = lastVelocity_Projected.normalized * lastVelocity.magnitude;

// drag

// all projected on circle
Vector2 projectedSum = gravityVec_Projected + lastVelocity_Projected;

velocity = projectedSum;
position += projectedSum;
position = position.normalized * distanceToCenter;

transform.position = position;
}
``````

I lost speed by projecting the previous velocity, if I scale it to what it was before, the pendulum goes forever without losing height.

Now the big question is: is this physically correct?
In a vacuum with zero friction, would a pendulum ever stop when affected by gravity? Is energy lost in centrifugal force?

1 Like

Seems like the answer is Yes - a pendulum wouldnâ€™t stop at zero friction.

1 Like

Well itâ€™s not â€śphysically correctâ€ť if thereâ€™s â€śzero frictionâ€ť anyway so I wouldnâ€™t worry about it.

The main issue you have when trying to make things perpetual on a computer is compound numerical errors whether due to floating-point precision or time-integration issues. As long as you do work to ensure the total energy in the system is periodically kept the same then youâ€™re good because youâ€™re explicitly removing compound errors that way.

Personally, for something like SHM with no external interaction, Iâ€™d go down the Sine route detailed above but if you got it working then thatâ€™s good too.

4 Likes