We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I know simulating a pendulum can be done by using polar coordinates and angular velocity etc. But I want to do it, by just using the Tension and Gravity forces acting on the 'bob', the resultant of which will 'supposedly' perform the swinging motion. The code I have is as follows:
The Main Class :
Mover bob;
PVector anchor;
float len;
PVector tension;
PVector gravity;
void setup() {
size(640, 380);
anchor = new PVector(width/2, 0);
bob = new Mover();
gravity = new PVector(0, 0.4);
tension = new PVector(0, 0);
len = dist(bob.pos.x, bob.pos.y, anchor.x, anchor.y);
}
void applyForces() {
tension = PVector.sub(anchor, bob.pos);
float str = bob.vel.magSq()/len + gravity.mag()*cos(bob.getAngle(anchor));
tension.setMag(str);
bob.applyForce(tension);
bob.applyForce(gravity);
}
void draw() {
background(50);
println(dist(bob.pos.x, bob.pos.y, anchor.x, anchor.y));
applyForces();
bob.update();
bob.render();
}
The Mover class :
class Mover {
PVector pos;
PVector vel;
PVector acc;
float mass = 1;
Mover() {
pos = new PVector(width/2.2, height/4);
vel = new PVector();
acc = new PVector();
}
float getAngle(PVector anchor) {
PVector temp1 = PVector.sub(pos, anchor);
PVector temp2 = PVector.sub(new PVector(anchor.x, height), anchor);
float angle = PVector.angleBetween(temp1, temp2);
return angle;
}
void applyForce(PVector force) {
PVector f = PVector.div(force, mass);
acc.add(f);
}
void update() {
vel.add(acc);
pos.add(vel);
acc.mult(0);
}
void render() {
fill(255);
ellipse(pos.x, pos.y, 30, 30);
}
}
Answers
@aizen -- you have said what you are trying to do, and you have shared code. What is your specific question at this point? What is not working, or where are you stuck or confused?
The problem is that if you run the sketch and check the console output, the length is not constant, and moreover, if I set the bob's position higher than the anchor's position, it behaves weirdly, (maybe it is because of the way the angle is calculated in this code). So, is there some way to correct these things.
Numbers stored using the
float
only have an accuracy of 6-7 significant digits and the problem is exaggerated because thepos
andvel
vectors are cumulative so any error is accumulated as well. This is happening every frame, 60 times a second so errors can soon accumulate.In the
AI for 2D Games
library the autonomous agents are updated using Newtonian physics i.e. velocity/acceleration/force. Internally the library uses thedouble
data type throughout to avoid this problem.so, you are suggesting that using 'double' instead of float should fix the first problem. I will definitely check that out.. Regarding the second issue of the weird behavior when the bob's position is set higher than the anchor, do you have any solution? Would love to get that problem solved too..
@quark well, I tried with double, but the cosine function and the PVector class doesn't take in double values, they only accept float. So no progress with that.
You will have to create your own vector class with double attributes and use that instead of PVector.
Alternatively use the Vector2D class I created in the AI library. To do that
1) Create a new tab on your sketch called exactly
Vector2D.java
2) Copy the source code from the Vector2Dclass but without the package statement` line
Instead of using Processing's trig functions use the ones from Java's Math class e.g.
Math.cos(double), Math.sin(double) etc.
I have not tried moving the bob's position above the anchor, but the tension force should be zero if the bob is above the anchor or inside the radius of the pendulum
@quark, dunno exactly when, but
package
is compatible w/ the PDE now! $-)That can be proved in 1 of my recent sketches below:
https://Forum.Processing.org/two/discussion/23471/combining-two-pieces-of-code/p2#Item_1
Where I can use
import deadpixel.command.Command;
to access the ".java" tab:https://GitHub.com/GoToLoop/command/blob/patch-1/src/deadpixel/command/Command.java
Which contains statement:
package deadpixel.command;
in it. :>Although we can still get it working w/o the
import
keyword in the ".pde" tab! @-)I think there is a mistake in your force formula too.. the tension in the string is equal to mg * cos theta, not mg * cos theta + Vel^2 / lenignore that. :) I can't find the delete button
Doubles are better, but they still accumulate error. Another (more robust) way to work around cumulative errors is to avoid accumulating processes. There are many ways using the built-in PVector methods. For one example, you could periodically reassert the length of the vector with
setMag()
, containing drift:A common pattern to avoid cumulative drift is to always apply a time step to calculating the position from the origin -- rather than calculating each position from the previous position. But since you've explicitly said you don't want to do that, you could think of this process as being like rigidity in the pendulum string/rod material.
When you said the length wasn't constant, do you mean it gradually increased? I tried this same approach to model a pendulum, but in my sketch, the pendulum constantly floats downwards.