Calculate spin frequency from rotation change in degrees - javascript

I have an object that rotates in the same direction at a variable speed.
I have the ability to measure the angle of this object in degrees (0-360) every frame (fps variable value, but I can rely on a minimum 30 fps).
How can I measure the rotation speed of this object in any units per 100 ms?

If we lock the frame rate to a certain fps (let's call it x), we can use the fact that the time between frames will always be 1/x seconds. Let us call the angle difference between two frames y. Assuming you use degrees, if we divide 360 by the change in angle between two frames (360/y), we end up calculating the number of frames we need to do one full rotation. Multiplying this by 1/x gives us the time it takes to do one full rotation.
To put it simply, do this calculation to find the time taken to do one full rotation at this moment in time: (1/x) * (360/y). We will call this result t.
Next, we find the rotational frequency of the object, which is done by the calculation 1/t. This is the number of revolutions per second. We can call this value f.
In order to finally calculate the rotational speed, we will do the following calculation: 2*π*f. This will give us the rotational speed, with units radians per second.
To convert this to radians per 100ms, we divide our calculation by 10.
To summarise, this is the calculation you will need: (0.2*π) / ((1/x) * (360/y))
Resources used:
https://www.webassign.net/question_assets/unccolphysmechl1/lab_5/manual.html

Related

How can I predict the stopping angle of a spinning wheel?

I'm trying to predict the angle in which a spinning wheel will stop if it is slowed down to a rotational speed of 0 over a certain time.
For example;
If my wheel is spinning at +20 degrees per tick, and it reaches a set angle of say, 720 degrees, where I then begin to slow it down to a stop over 5 seconds, what angle will it rest at.
I have been looking at a lot of existing questions and material for this and am aware of the sort of maths I need to be working with; getting the deceleration speed and rotational velocity, but I'm struggling to use this information to predict an end angle.
This was a particularly useful resource but I am still unsure on how to translate this math into a predicted resting angle.
https://physics.stackexchange.com/questions/142761/how-to-model-a-very-simple-spinning-wheel
Thanks in advance.
The answer depends on the mechanism that stops it, but if we assume that it's simple friction, then deceleration is constant and the answer is easy:
If it starts off at 20 degrees per tick, then the average speed during the slowdown period is 10 degrees per tick, so 720 + 10 * 5 * ticks_per_second degrees.
Assuming constant deceleration (dry friction), the angular speed decreases linearly. Hence, the average speed is the half* of the initial speed, or
A / T = Ω / 2
where A is the traversed angle, T the time to stop and Ω the initial angular speed.
Hence
A = T Ω / 2
*For the same reason that the area of a right triangle is the half of the area of the bounding rectangle.

Phaser calculate needed y velocity for given y point

In my mobile game, the main character needs to jump to a specific y point before starting to fall down again due to gravity. How could I calculate the y velocity I would need to reach (at peak) a given y position with a given gravity?
I tried to do this with a tween instead of arcade physics because it was exactly what I needed (distance traveled over time with a gravity-like effect), but the performance was not good and was constantly sputtering.
I'm currently using Phaser 2.6.2. Thanks!
There are 2 kinds of time in games, cycle based time and deltaTime.
In a cycle based scenario, the physics don't shift to account for lag so the best solution is this:
You start off with number sequence where you compound gravity with the previous number in the sequence until your sum total equals your desired height.
For an example, I will use height = 75, gravity = 5, and jumpForce=unknown
(5+10+15+20+25)=75
The jump force you need to reach this height will be the last number in the sequence which is "25".
In a deltaTime Scenario (as used in this case), the physics are abstracted to try to adjust to time.
So, if you have 5fps, you'll have 5 cycles/second. if you have 20 fps, you'll have 20 cycles per second; so, this abstraction makes the above irrelevant.
Instead use the standard gravity formula of height = velocity^2 / (2 * gravity)., because this will better model to the formulas used by delta time engines.

Acceleration over time

Scenario
I am working on a top-down view game in which enemies move towards certain positions. The destination being moved towards will often change drastically - sometimes while the enemy is still in motion towards the previous destination...
I want to achieve movement which is more realistic than linear movement, so there should be some acceleration and deceleration as enemies switch between the destinations.
Steering (direction) is not a factor. You may assume the sprites will move much like a hovercraft, drifting between the destinations as quickly as it can manage with respect to acceleration and deceleration.
For simplicity - lets assume there is only 1 dimension (Y) instead of X and Y... the movement should emulate a car which can only move north or south.
Since we are considering realistic movement in this scenario, you might not be surprised that a maximum speed over time is also a consideration. The enemy should never exceed it's own maximum speed; enemies store their own maximum speed in a variable.
One final consideration is that enemies will not only have a 'maximum speed' value, but it will also have a 'maximum acceleration' value - this would be the thing which guides how quickly each enemy can respond to moving in the opposite direction.
For simplicity, assume that the enemy does not have any movement friction... when it stops accelerating, it just keeps cruising at the current velocity forever.
Example
For context, lets elaborate on the car example. A particular car has:
Maximum speed: 10 meters per second
Maximum acceleration: can reach top speed in 2 seconds
(Other factors like destination y-pos, position y-pos, current velocity, etc)
Just like when I'm driving a car, I imagine all of these values are present, but I can't change them. All I can really change is how much I'm putting my foot on the acceleration/brake. Let's call this the 'throttle'. Like the acceleration pedal in a car, I can change this value to any amount at any time, in no time at all.
I can plant my foot down (throttle=1), let go of the pedal immediately (throttle=0), and even change into reverse and plant my foot down again (throttle=-1). Lets assume these changes in throttle are INSTANT (unlike speed or acceleration, which grow/shrink over TIME)
All that said, I imagine the only value that I really need to calculate is what the throttle should be, since thats the only thing I can control in the vehicle.
So, how then do I know how much throttle to use at any given moment, to arrive as quickly as possible to a destination (like some traffic lights) without overshooting my destination? I will need to know how much to push down the accelerator, briefly not accelerate at all, and then how hard decelerate as I'm closing in on the destination.
Preempted movement
This game will likely have an online component. That said, players will be transmitting their positions over a socket connection... however even the best connection could never achieve sending positions frequently enough to achieve smooth movement - you need interpolation. You need to send the 'velocity' (speed) along with the co-ordinates so that I can assume future positions in the time between packets being received.
For that reason, Tweens are a no-go. There would be no way to send a tween, then accurately inform the other parties at what point along each tween each entity currently is (I mean, I guess it is possible, but horrendously overcomplicated and probably involves rather large packet sends, and is probably also very exploitable in terms of the online component), then you need to consider aborting Tweens as the destinations change, etc.
Don't get me wrong, I could probably already model some very realistic movement with the ease-in/ease-out functionality of Tweens, and it would look great, but in an online setting that would be.. very messy.
How's it look so far?
So, essentially I have established that the primary aspect which needs to be calculated at any time is how much throttle to use. Let's work through my logic...
Imagine a very basic, linear movement over time formula... it would look like this:
Example 1 - position over time
currentDY = 5; // Current 'velocity' (also called Delta Y or 'DY')
currentY += currentDY * time // Current Y pos is increased by movement speed over time.
As you can see, at any given moment, the Y position increases over time due to the 'velocity' or DY (over time). Time is only a factor ONCE, so once we reach the destination we just set the DY to zero. Very sharp unrealistic movement. To smoothen the movement, the velocity ALSO needs to change over time...
Example 2 - velocity over time
throttle = -1
currentDY += throttle * time;
currentY += (currentDY * time);
//Throttle being -1 eventually decelerates the DY over time...
Here, the throttle is '-1' (maximum reverse!), so over time this will reduce the velocity. This works great for realistic acceleration, but provides no realistic anticipation or deceleration.
If we reach the destination this time, we can set the throttle to '0'... but it's too late to brake, so the resulting enemy will just keep moving past the target forever. We could throttle = '1' to go back, but we'll end up swinging back and forth forever.
(Also note that the maximum acceleration and speed isn't even a factor yet - it definately needs to be! The enemy cannot keep ramping up their speed forever; velocity delta AND ALSO acceleration delta need to have limits).
All that said, it's not enough to simply change velocity over time, but we also need be able to anticipate how much to decelerate (i.e. 'backwards throttle') BEFORE IT HAPPENS. Here's what I've got so far, and I'm practically certain this is the wrong approach...
Example 3 - throttle over time?? (I'm stuck)
guideY = currentY + (currentDY * (timeScale * 3000));
dist = endY - guideY;
throttle = Math.max(-1, Math.min(1, dist / 200));
currentDY += throttle * time;
currentY += (currentDY * time);
As you can see, this time we attempt to anticipate how much throttle to use by guessing where the enemies position will be in an arbitrary time in the future (i.e. 3 seconds). If the guideY went past the destination, we know that we have to start BRAKING (i.e. reducing speed to stop on top of the destination). By how much - depends on how far away the enemies future position is (i.e. throttle = dist / 200;)
Here's is where I gave up. Testing this code and changing the values to see if they scale properly, the enemy always swings way over the destination, or takes far too long to 'close in' on the destination.
I feel like this is the wrong approach, and I need something more accurate. It feels like I need an intersection to correctly anticipate future positions.
Am I simply using the wrong values for the 3 seconds and dist / 200, or am I not implementing a fully working solution here?
Presently, compared to the linear movement, it always seems to take 8 times longer to arrive at the target position. I haven't even reached the point of implementing maximum values for DeltaVelocity or DeltaAcceleration yet - the accepted solution MUST consider these values despite not being present in my JSFiddle below...
Test my logic
I've put all my examples in a working JSFiddle.
JSFiddle working testbed
(Click the 'ms' buttons below the canvas to simulate the passing of time. Click a button then press+hold Return for very fast repetition)
The sprite is initially moving in the 'wrong' direction - this is intended for testing robustness - It assumes an imaginary scenario where we just finished moving as fast as possible toward an old destination far lower on the screen, and now we need to suddenly start moving up...
As you can see, my third example (see the update function), the time for the sprite to 'settle' at the desired location takes far longer than it should. My math is wrong. I can't get my head around what is needed here.
What should the throttle be at any given time? Is using throttle even a correct approach? Your assistance is very appreciated.
Tiebreaker
Alright, I've been stuck on this for days. This question is going up for some phat bounty.
If a tiebreaker is required, the winner will need to prove the math is legit enough to be tested in reverse. Here's why:
Since the game also comprises of a multiplayer component, enemies will be transmitting their positions and velocities.
As hacking protection, I will eventually need a way to remotely 'check' if the velocity and position at between any two sample times is possible
If the movement was too fast based on maximum velocity and acceleration, the account will be investigated etc. You may assume that the game will know the true maximum acceleration and velocity values of the enemies ahead of time.
So, as well as bounty, you can also take satisfaction in knowing your answer will contribute to ruining the lives of filthy video game cheaters!
Edit 2: Fiddle added by answer author; adding into his answer in case anyone else finds this question: http://jsfiddle.net/Inexorably/cstxLjqf/. Usage/math explained further below.
Edit 1: Rewritten for clarification received in comments.
You should really change your implementation style.
Lets say that we have the following variables: currentX, currentY, currentVX, currentVY, currentAX, currentAY, jerk.
currentVX is what would have been your currentDX. Likewise, currentAX is the x component of your delta velocity value (accel is derivative of velocity).
Now, following your style, we're going to have a guideX and a guideY. However, there is another problem with how you're doing this: You are finding guideY by predicting the target's position in three seconds. While this is a good idea, you're using three seconds no matter how close you are to the target (no matter how small dist is). So when the sprite is 0.5 seconds from the target, it's going to still be moving towards the target's estimated position (three seconds into the future). This means it won't actually be able to hit the target, which seems to be the problem that you implied.
Moving on, recall the previous variables that I mentioned. Those are the current variables -- ie, they will be updated at every call after some seconds have been passed (like you have been doing before). You also mentioned a desire to have maxV, and maxA.
Note that if you have a currentVX of 5 and a currentVY of 7, the velocity is (5^2+7^2)^0.5. So, what you're going to want to do each time you're updating the 'current' archetype of variables is before updating the value, see if the magnitude (so sqrt(x^2+y^2) of those variables like I showed with velocity) will exceed the respective maxV, maxA, or jmax values that you have set as constants.
I'd also like to improve how you generate your guide values. I'm going to assume that the guide can be moving. In this case, the target will have the values listed above: x, y, vx, vy, ax, ay, jx, jy. You can name these however you'd like, I'm going to use targetX, targetY... etc to better illustrate my point.
From here you should be finding your guide values. While the sprite is more than three seconds away from the target, you may use the target's position in three seconds (note: I recommend setting this as a variable so it is simple to modify). For this case:
predictionTime = 3000*timescale; //You can set this to however many seconds you want to be predicting the position from.
If you really wanted to, you could smooth the curve using integration functions or loops for the guide values to get a more accurate guide value from the target values. However, this is not a good idea because if you ever implement multiple targets / etc, it could have a negative impact on performance. Thus, we will use a very simple estimation that is pretty accurate for being such low cost.
if (sprite is more than predictionTime seconds away from the target){
guideX = targetX + predictionTime * targetVX;
guideY = targetY + predictionTime * targetVY;
}
Note that we didn't account for the acceleration and jerk of the target in this, it's not needed for such a simple approximation.
However, what if the sprite is lese than predictionTime seconds away from the target? In this case we want to start increasingly lessening our predictionTime values.
else{
guideX = targetX + remainingTime * targetVX;
guideY = targetY + remainingTime * targetVY;.
}
Here you have three choices on finding the value of remaining time. You can set remainingTime to zero, making the guide coordinates the same as the targets. You can set remainingTime to be sqrt((targetX-currentX)^2+(targetY-currentY))/(sqrt(currentVX)^2+(currentVY)^2), which is basically distance / time in 2d, a cheap and decent approximation. Or you can use for loops as mentioned before to simulate an integral to account for the changing velocity values (if they are deviating from maxV). However, generally you will be remaining at or close to maxV, so this is not really worth the expense. Edit: Also, I'd also recommend setting remainingTime to be 0 if it is less than some value (perhaps about 0.5 or so. This is because you don't want hitbox issues because your sprite is following guide coordinates that have a slight offset (as well as the target moving in circles would give it a larger velocity value while changing direction / essentially a strong evasion tactic. Maybe you should add something in specifically for that.
We now have the guideX and guideY values, and account for getting very close to a moving target having an effect on how far from the target the guide coordinates should be placed. We will now do the 'current' value archetype.
We will update the lowest derivative values first, check to see if they are within bounds of our maximum values, and then update the next lowest and etc. Note that JX and JY are as mentioned before to allow for non constant acceleration.
//You will have to choose the jerk factor -- the rate at which acceleration changes with respect to time.
//We need to figure out what direction we're going in first. Note that the arc tangent function could be atan or whatever your library uses.
dir = arctan((guideY-currentY)/(guideX-currentX));
This will return the direction as an angle, either in radians or degree depending on your trig library. This is the angle that your sprite needs to take to go in the direction of guide.
t = time; //For ease of writing.
newAX = currentAX + jerk*t*cos(dir);
newAY = currentAY + jerk*t*sin(dir);
You may be wondering how the newAx value will ever decrease. If so, note that cos(dir) will return negative if guide is to the left of the target, and likewise sin(dir) will return negative if the sprite needs to go down. Thus, also note that if the guide is directly below the sprite, then newAx will be 0 and newAY will be a negative value because it's going down, but the magnitude of acceleration, in other words what you compare to maxA, will be positive -- as even if the sprite is moving downwards, it's not moving at negative speed.
Note that because cos and sin are of the same library as atan presumably, so the units will be the same (all degrees or all radians). We have a maximum acceleration value. So, we will check to make sure we haven't exceeded that.
magnitudeA = sqrt(newAX^2+newAY^2);
if (magnitudeA > maxA){
currentAX = maxA * cos(dir);
currentAY = maxA * sin(dir);
}
So at this point, we have either capped our acceleration or have satisfactory acceleration components with a magnitude less than maxA. Let us do the same for velocity.
newVX = currentVX + currentAX*t;
newVY = currentVY + magnitudeA*t*sin(dir);
Note that I have included two ways to find the velocity components here. Either one works, I'd recommend choosing one and using it for both x and y velocity values for simplicity. I just wanted to highlight the concept of magnitude of acceleration.
magnitudeV = sqrt(newVX^2+newVY^2);
if (magnitudeV > maxV){
currentVX = maxV * cos(dir);
currentVY = maxV * sin(dir);
}
We'd also like to stop boomeranging around our target. However, we don't want to just say slow down alot like you did in your JSFiddle, because then if the target is moving it will get away (lol). Thus, I suggest checking how close you are, and if you are in a certain proximity, reduce your speed linearly with distance with an offset of the target's speed. So set closeTime to something small like 0.3 or what ever feels good in your game.
if (remainingTime < closeTime){
//We are very close to the target and will stop the boomerang effect. Note we add the target velocity so we don't stall while it's moving.
//Edit: We should have a min speed for the enemy so that it doesn't slow down too much as it gets close. Lets call this min speed, relative to the target.
currentVX = targetVX + currentVX * (closeTime - remainingTime);
currentVY = targetVY + currentVY * (closeTime - remainingTime);
if (minSpeed > sqrt(currentVX^2+currentVY^2) - sqqrt(targetVX^2-targetVY^2)){
currentVX = minSpeed * cos(dir);
currentVY = minSpeed * sin(dir);
}
}
magnitudeV = sqrt(currentVX^2+currentVY^2);
At this point we have good values for velocity too. If you going to put in a speedometer or check the speed, you're interested in magnitudeV.
Now we do the same for position. Note you should include checks that the position is good.
newX = currentX + currentVX*t;
newY = currentY + currentVY*t;
//Check if x, y values are good.
current X = newX; currentY = newY;
Now everything has been updated with the good values, and you may write to the screen.

sine wave drawing using JavaScript

I am working on creating a simple snow simulation, but I am failing horribly on the math. Basically, when a snowflake is initialized, it's x position is set randomly somewhere on the svg canvas. Then from there, it falls straight down. It should be simulating a sine wave (the x coordinates should move like a sine wave).
I haven't done trig since last year so i'm a bit rusty. Math.sin() takes radians I believe, so I multiply by 180, then divide by pi to convert to degrees?
Assume x is the current x position of a snowflake, and width is the width of the canvas.
x += (Math.sin(((x/width)*(180/Math.PI)))*width)
It kind of works, but it is all over the place. I have a vague idea of what i'm doing, but I can't seem to push the math from my brain to code.
Here's a JSFiddle:
What am I doing incorrectly?
It should be:
x += A*Math.sin(F*(y/Height)*2*Math.PI);
where A is the amplitude, i.e. how many pixels you want the flake to shift left and right (note that total shift will be 2*A). F is the frequency, or how often you want the flake to shift left and right (I'd set it at random between 2 and 10 for each flake).

2d parabolic projectile

I'm looking to create a basic Javascript implementation of a projectile that follows a parabolic arc (or something close to one) to arrive at a specific point. I'm not particularly well versed when it comes to complex mathematics and have spent days reading material on the problem. Unfortunately, seeing mathematical solutions is fairly useless to me. I'm ideally looking for pseudo code (or even existing example code) to try to get my head around it. Everything I find seems to only offer partial solutions to the problem.
In practical terms, I'm looking to simulate the flight of an arrow from one location (the location of the bow) to another. I have already simulated the effects of gravity on my projectile by updating its velocity at each logic interval. What I'm now looking to figure out is exactly how I figure out the correct trajectory/angle to fire my arrow at in order to reach my target in the shortest time possible.
Any help would be greatly appreciated.
Pointy's answer is a good summary of how to simulate the movement of an object given an initial trajectory (where a trajectory is considered to be a direction, and a speed, or in combination a vector).
However you've said in the question (if I've read you correctly) that you want to determine the initial trajectory knowing only the point of origin O and the intended point of target P.
The bad news is that in practise for any particular P there's an infinite number of parabolic trajectories that will get you there from O. The angle and speed are interdependent.
If we translate everything so that O is at the origin (i.e. [0, 0]) then:
T_x = P_x - O_x // the X distance to travel
T_y = P_y - O_y // the Y distance to travel
s_x = speed * cos(angle) // the X speed
s_y = speed * sin(angle) // the Y speed
Then the position (x, y) at any point in time (t) is:
x = s_x * t
y = s_y * t - 0.5 * g * (t ^ 2)
so at impact you've got
T_x = s_x * t
T_y = -0.5 * g * (t ^ 2) + s_y * t
but you have three unknowns (t, s_x and s_y) and two simultaneous equations. If you fix one of those, that should be sufficient to solve the equations.
FWIW, fixing s_x or s_y is equivalent to fixing either speed or angle, that bit is just simple trigonometry.
Some combinations are of course impossible - if the speed is too low or the angle too high the projectile will hit the ground before reaching the target.
NB: this assumes that position is evaluated continuously. It doesn't quite match what happens when time passes in discrete increments, per Pointy's answer and your own description of how you're simulating motion. If you recalculate the position sufficiently frequently (i.e. 10s of times per second) it should be sufficiently accurate, though.
I'm not a physicist so all I can do is tell you an approach based on really simple process.
Your "arrow" has an "x" and "y" coordinate, and "vx" and "vy" velocities. The initial position of the arrow is the initial "x" and "y". The initial "vx" is the horizontal speed of the arrow, and the initial "vy" is the vertical speed (well velocity really but those are just words). The values of those two, conceptually, depend on the angle your bowman will use when shooting the arrow off.
You're going to be simulating the progression of time with discrete computations at discrete time intervals. You don't have to worry about the equations for "smooth" trajectory arcs. Thus, you'll run a timer and compute updated positions every 100 milliseconds (or whatever interval you want).
At each time interval, you're going to add "vx" to "x" and "vy" to "y". (Thus, note that the initial choice of "vx" and "vy" is bound up with your choice of time interval.) You'll also update "vx" and "vy" to reflect the effect of gravity and (if you feel like it) wind. If "vx" doesn't change, you're basically simulating shooting an arrow on the moon :-) But "vy" will change because of gravity. That change should be a constant amount subtracted on each time interval. Call that "delta vy", and you'll have to tinker with things to get the values right based on the effect you want. (Math-wise, "vy" is like the "y" component of the first derivative, and the "delta vy" value is the second derivative.)
Because you're adding a small amount to "vy" every time, the incremental change will add up, correctly simulating "gravity's rainbow" as your arrow moves across the screen.
Now a nuance you'll need to work out is the sign of "vy". The initial sign of "vy" should be the opposite of "delta vy". Which should be positive and which should be negative depends on how the coordinate grid relates to the screen.
edit — See #Alnitak's answer for something actually germane to your question.

Categories