Main content
Computer programming
Course: Computer programming > Unit 5
Lesson 7: Oscillations- Oscillation amplitude and period
- Challenge: Rainbow slinky
- Oscillation with angular velocity
- Challenge: Spaceship ride
- Waves
- Challenge: Many waves
- Trig and forces: the pendulum
- Challenge: Pendulum puppet
- Spring forces
- Project: Curling, crawling, circling creatures
© 2023 Khan AcademyTerms of usePrivacy PolicyCookie Notice
Oscillation with angular velocity
An understanding of the concepts of oscillation, amplitude, and frequency/period is often required in the course of simulating real-world behaviors. However, there is a slightly easier way to rewrite the above example with the same result. Let’s take one more look at our oscillation formula:
var x = amplitude * sin(TWO_PI * frameCount / period);
And let’s rewrite it a slightly different way:
var x = amplitude * sin(some value that increments slowly);
If we care about precisely defining the period of oscillation in terms of frames of animation, we might need the formula the way we first wrote it, but we can just as easily rewrite our example using the concept of angular velocity (and acceleration) from the Angular Motion lesson. Assuming:
var angle = 0;
var aVelocity = 0.03;
...in
draw()
, we can simply say:angle += aVelocity;
var x = amplitude * sin(angle);
...where
angle
is our “some value that increments slowly.”Here's our modified program:
Just because we’re not referencing it directly doesn’t mean that we’ve eliminated the concept of period. After all, the greater the angular velocity, the faster the circle will oscillate (therefore lowering the period). In fact, the number of times it takes to add up the angular velocity to get to
TWO_PI
is the period or:period = TWO_PI / angular velocity
Let’s expand this example a bit more and create an
Oscillator
object. And let’s assume we want the oscillation to happen along both the x-axis (as above) and the y-axis. To do this, we’ll need two angles, two angular velocities, and two amplitudes (one for each axis). Another perfect opportunity for PVector
!Read through the code in the program below:
This "Natural Simulations" course is a derivative of "The Nature of Code" by Daniel Shiffman, used under a Creative Commons Attribution-NonCommercial 3.0 Unported License.
Want to join the conversation?
- The third step of "Challenge: Spaceship ride" says:
"Spin the ships!
Okay, now let's really give them a ride - calculate the angular acceleration based on how far away each ship is from the center, and rotate just the ship based on that. That means that your ship will need to keep track of its angular velocity and current angle, and each call to oscillate() will add to those values based on the angular acceleration that you calculate."
Can I get a bigger hint about what that angular acceleration formula is supposed to look like?(6 votes)- One would think
this.position.mag()
is correct, but the grader only seems to likedist(this.position.x, this.position.y, 0, 0)
(7 votes)
- On Step 3 of the next challenge, where do you put the constrain function? Here is my code so far:
angleMode = "radians";
var Spaceship = function() {
this.angle = new PVector();
this.velocity = new PVector(random(-0.02, 0.22), random(-0.04, 0.13));
this.amplitude = new PVector(random(20, width/2), random(20, width/2));
this.position = new PVector(0, 0);
this.aAccel = 0;
this.aVel = 0;
};
Spaceship.prototype.oscillate = function() {
this.angle.add(this.velocity);
this.position.set(
sin(this.angle.x) * this.amplitude.x,
sin(this.angle.y) * this.amplitude.y
);
// Calculate the angular acceleration, based on distance
var acceleration = dist(this.position.x, this.position.y, 0, 0);
var acceleration = constrain(this.aVel, 0.5, 1.5);
// Add it to your angVelocity property, scalling it
// to a realistic amount
this.aAccel += acceleration / 10000;
this.aVel += this.aAccel;
};
Spaceship.prototype.display = function() {
pushMatrix();
translate(width/2, height/2);
stroke(181, 63, 0);
strokeWeight(9);
line(0, 0, this.position.x, this.position.y);
imageMode(CENTER);
translate(this.position.x, this.position.y);
rotate(this.aVel);
image(getImage("space/octopus"),
0, 0, 80, 100);
popMatrix();
};
var ships = [];
for (var i = 0; i < 10; i++) {
ships.push(new Spaceship());
}
draw = function() {
background(174, 218, 232);
for (var i = 0; i < ships.length; i++) {
ships[i].oscillate();
ships[i].display();
}
};(10 votes) - Here's a code dump for final code:
angleMode = "radians";
var Spaceship = function() {
this.angle = new PVector();
this.velocity = new PVector(random(-0.02, 0.02), random(-0.02, 0.02));
this.amplitude = new PVector(random(20, width/2), random(20, width/2));
this.position = new PVector(0, 0);
this.aAngle = 0;
this.aVelocity = 0;
};
Spaceship.prototype.oscillate = function() {
this.angle.add(this.velocity);
this.position.set(
sin(this.angle.x) * this.amplitude.x,
sin(this.angle.y) * this.amplitude.y);
var s = dist(this.position.x, this.position.y, 0, 0);
this.aAngle += s /10000;
this.aAngle = constrain(this.aAngle, -0.1, 0.1);
this.aVelocity += this.aAngle;
};
Spaceship.prototype.display = function() {
pushMatrix();
translate(width/2, height/2);
stroke(181, 63, 0);
strokeWeight(9);
line(0, 0, this.position.x, this.position.y);
translate(this.position.x, this.position.y);
imageMode(CENTER);
rotate(this.aVelocity);
image(getImage("space/octopus"),
0, 0,
80, 100);
popMatrix();
};
var ships = [];
for (var i = 0; i < 10; i++) {
ships.push(new Spaceship());
}
draw = function() {
background(174, 218, 232);
for (var i = 0; i < ships.length; i++) {
ships[i].oscillate();
ships[i].display();
}
};
//Note that my aAngle, and aVelocity might be mixed around or not, I got kindve confused on this one. but I hope I can help people pass the constrain part.(8 votes) - Why does KA get us to do challenges yet they haven't taught us how to do it yet?(6 votes)
- Even if they haven't taught you exactly how to solve the particular problem, they have taught you the basic concepts needed to complete the challenge.
There's a reason why they call it a challenge. :)(3 votes)
- In the step 3 of next challenge, I didn't get why it should be
dist(this.position.x, this.position.y, 0, 0)
instead ofdist(this.position.x, this.position.y, width/2, height/2)
as distance should be measured from the center?(4 votes)- It is already translated translate(width/2, height/2);(6 votes)
- I've always wondered this but never got the answer: What in programs is " this. " ?
Like for example: this.angle(3 votes)this
refers to the object it is inside. This concept is covered here: https://www.khanacademy.org/computing/computer-programming/programming/object-oriented/p/object-types(5 votes)
- The "Challenge: Spaceship Ride" has me stumped. My code lets the ships rotate, but the grader won't let me pass. I've seen lots of people say, "Use dist(this.position.x, this.position.y, 0, 0)/10000;" but if I do that, the orange words say, "Can you divide it by a bigger number to make it more realistic?" and won't go away until I change the second 0 in dist(); to a 1. Adding "/10000" makes no difference. Here's my code:
angleMode = "radians";
var Spaceship = function() {
this.angle = new PVector();
this.velocity = new PVector(random(-0.02, 0.22), random(-0.04, 0.13));
this.amplitude = new PVector(random(20, width/2), random(20, width/2));
this.position = new PVector(0, 0);
this.ro = 0;
this.rot = 0;
};
Spaceship.prototype.oscillate = function() {
this.angle.add(this.velocity);
this.position.set(
sin(this.angle.x) * this.amplitude.x,
sin(this.angle.y) * this.amplitude.y);
// Calculate the angular acceleration, based on distance
var acceleration = dist(this.position.x, this.position.y, 1, 0);
// Add it to your angVelocity property, scalling it
// to a realistic amount
this.ro += acceleration / 3;
this.rot += this.ro;
};
Spaceship.prototype.display = function() {
pushMatrix();
translate(width/2, height/2);
stroke(181, 63, 0);
strokeWeight(9);
line(0, 0, this.position.x, this.position.y);
imageMode(CENTER);
translate(this.position.x, this.position.y);
//(I placed "this.rot" inside rotate();--before, there was "PI")
rotate(this.rot);
image(getImage("space/octopus"),
0, 0, 80, 100);
popMatrix();
};
var ships = [];
for (var i = 0; i < 10; i++) {
ships.push(new Spaceship());
}
draw = function() {
background(174, 218, 232);
for (var i = 0; i < ships.length; i++) {
ships[i].oscillate();
ships[i].display();
}
};(4 votes) - I noticed in the above code this line
this.angle = new PVector();
What does not adding any parameters toPVector
do?(3 votes)- Why don't you do a
println(this.angle);
and report your findings back to us?(2 votes)
- For some reason, in the spaceship ride challenge 'constraining' the angular acceleration [dist(this.position.x,this.position.y,0,0)/10000 worked, as opposed to 'constraining' the angular velocity. Am I missing something? Is anyone feeling the same?(3 votes)
- In the next exercise on step two, I have the same code as what other people have posted here, but it won't let me pass, and the ropes oscillate while the spaceships sit vibrating in the middle. Does anyone know what could be going on?
For the record, here is the salient part of my code:Spaceship.prototype.display = function() {
pushMatrix();
translate(width/2, height/2);
stroke(181, 63, 0);
strokeWeight(9);
line(0, 0, this.position.x, this.position.y);
imageMode(CENTER);
translate(this.position.x, this.position.y);
rotate(PI);
image(getImage("space/octopus"),
this.position.x, this.position.y,
80, 100);
popMatrix();
};
EDIT: I figured out that I had to change the x and y of the image to "0,0" but I would still be interested in knowing why I had to to that.(2 votes)- I had the same issue. In this instructions they say to draw the images at the origin and then to translate the image. That is why the image has to take x and y values of (0, 0).
Although there are other ways to make it look right, those methods don't begin by drawing the image at the origin, and therefore don't fulfill the requirements of the challenge.(1 vote)