Main content

### Course: Computer programming - JavaScript and the web > 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

© 2024 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 like`dist(this.position.x, this.position.y, 0, 0)`

(7 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.(10 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) - Why does KA get us to do challenges yet they haven't taught us how to do it yet?(7 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. :)(2 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 of`dist(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(2 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 to`PVector`

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)
- I finished the Spaceship ride challenge, and it says that I have completed all 3 steps. But nothing appears on the screen. Help! Here is my code;

angleMode = "radians";

var Spaceship = function() {

this.angle = new PVector();

this.velocity = new PVector(random(-0.1, 0.6), random(-0.06, 0.05));

this.amplitude = new PVector(random(20, width/2), random(20, width/2));

this.position = new PVector(0, 0);

this.vel = 0;

this.angl = 0;

};

Spaceship.prototype.oscillate = function() {

pushMatrix();

translate(width/2,height/2);

var acceleration = dist(0,0,this.position.x,this.position.y);

this.vel +=acceleration/10000;

this.vel = constrain(this.vel,0.02,0.06);

this.angl += this.vel;

this.angle.add(this.velocity);

this.position.set(

sin(this.angle.x) * this.amplitude.x,

sin(this.angle.y) * this.amplitude.y);

};

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

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

}

};(2 votes)- Hi, I know it's been two years since you asked for help but I hope my answer will reach you.

The problem with your code is that you have translated to the wrong position in the oscillate function. You just need to remove the two lines`pushMatrix();`

translate(width/2,height/2);(1 vote)