I need to find the average Edit: total 2D velocity given multiple 2D velocities (speed and direction). A few examples:
Example 1
Velocity 1 is 90° at a speed of 10 pixels or units per second.
Velocity 2 is 270° at a speed of 5 pixels or units per second.
The average velocity is 90° at 5 pixels or units per second.
Example 2
Velocity 1 is 0° at a speed of 10 pixels or units per second
Velocity 2 is 180° at a speed of 10 pixels or units per second
Velocity 3 is 90° at a speed of 8 pixels or units per second
The average velocity is 90° at 8 pixels or units per second
Example 3
Velocity 1 is 0° at 10 pixels or units per second
Velocity 2 is 90° at 10 pixels or units per second
The average velocity is 45° at 14.142 pixels or units per second
I am using JavaScript but it's mostly a language-independent question and I can convert it to JavaScript if necessary.
If you're going to be using a bunch of angles, I would just calculate each speed,
vx = v * cos(theta),
vy = v * sin(theta)
then sum the x velocities and the y velocities separately as vector components and divide by the total number of velocities,
sum(vx) / total v, sum(vy) / total v
and then finally calculate the final speed and direction with your final vx and vy. The magnitude of the speed can be found by a simple application of pythagorean theorem, and then final angle should just be tan-1(y/x).
Per example #3
vx = 10 * cos(90) + 10 * cos(0) = 10,
vy = 10 * sin(90) + 10 * sin(0) = 10
so, tan-1(10/10) = tan-1(1) = 45
then a final magnitude of sqrt(10^2 + 10^2) = 14.142
These are vectors, and you should use vector addition to add them. So right and up are positive, while left and down are negative.
Add your left-to-right vectors (x axis).
Example 1 = -10+5 = -5
Example 2 = -8 = -8
Example 3 = 10 = 10. (90 degrees is generally 90 degrees to the right)
Add you ups and downs similarly and you get these velocities, your left-to-right on the left in the brackets, and your up-to-down on the right.
(-5, 0)
(-8,0)
(10, 10)
These vectors contain all the information you need to plot the motion of an object, you do not need to calculate angles to plot the motion of the object. If for some reason you would rather use speeds (similar to velocity, but different) and angles, then you must first calculate the vectors as above and then use the Pythagorean theorem to find the speed and simple trigonometry to get the angle. Something like this:
var speed = Math.sqrt(x * x + y * y);
var tangeant = y / x;
var angleRadians = Math.atan(tangeant);
var angleDegrees = angleRadians * (180 / Math.PI);
I'll warn you that you should probably talk to someone who know trigonometry and test this well. There is potential for misleading bugs in work like this.
From your examples it sounds like you want addition of 2-dimensional vectors, not averages.
E.g. example 2 can be represented as
(0,10) + (0,-10) + (-8, 0) = (-8,0)
The speed is then equal to the length of the vector:
sqrt(x^2+y^2)
To get average:
add each speed, and then divide by the number of speeds.
10mph + 20mph / 2 = 15
12mph + 14mph + 13mph + 16mph / 4 = 14 (13,75)
This is not so much average as it is just basic vector addition. You're finding multiple "pixel vectors" and adding them together. If you have a velocity vector of 2 pixels to the right, and 1 up, and you add it to a velocity vector of 3 pixels to the left and 2 down, you will get a velocity vector of 1 pixel left, and 1 down.
So the speed is defined by
pij = pixels going up or (-)down
pii = pixels going right or (-)left
speedi = pii1 + pii2 = 2-3 = -1 (1 pixel left)
speedj = pij1 + pij2 = 1-2 = -1 (1 pixel down)
From there, you need to decide which directions are positive, and which are negative. I recommend that left is negative, and down is negative (like a mathematical graph).
The angle of the vector, would be the arctan(speedj/speedi)
arctan(-1/-1) = 45 degrees
Related
The first IMU (called S1) is placed on the shoulder and works as a reference; the other (S2) is placed on the arm. They provide the quaternion of their rotation relative to the absolute reference (magnetic north and gravity vector). The simple idea is that I need to show the Yaw, Pitch and Roll differences between these two (e.g. an ideal abduction/adduction movement should have pitch contributions only). I started using quaternions, by calculating the rotation between the two (conj(q1) * q2) and then converting it to YPR angles by using:
# Rotation quaternion q1 = (w,x,y,z)
# unit = sum of squared elements (sqx = x^2, etc.)
yaw = math.atan2(2 * q1[2] * q1[0] - 2 * q1[1] * q1[3], sqx - sqy - sqz + sqw)
pitch = math.asin(2 * (q1[1] * q1[2] + q1[3] * q1[0]) / sqx + sqy + sqz + sqw)
roll = math.atan2(2 * q1[1] * q1[0] - 2 * q1[2] * q1[3], -sqx - sqy + sqz + sqw)
but this doesn't work in my case, since pitch and roll are not consistent in different arm positions. E.g. if relative Yaw is 90 deg, pitch and roll angles are interchanged. E.g. if I apply a pitch rotation to S2, it appears to be a roll rotation (since the rotation is on the y-axis for the reference sensor S1).
How can I avoid this?
Should I simply convert both quaternion to YPR angles and then calculate the difference of each pair (without using the difference between quaternions)? Maybe the "rotation" approach is not correct, since I don't need the inverse transformation but only the actual rotation for each axis?
Given a convex 3d polygon (convex hull) How can I determine the correct direction for normal surface/vertex vectors? As the polygon is convex, by correct I mean outward facing (away from the centroid).
def surface_normal(centroid, p1, p2, p3):
a = p2-p1
b = p3-p1
n = np.cross(a,b)
if **test including centroid?** :
return n
else:
return -n # change direction
I actually need the normal vertex vectors as I am exporting as a .obj file, but I am assuming that I would need to calculate the surface vectors before hand and combine them.
This solution should work under the assumption of a convex hull in 3d. You calculate the normal as shown in the question. You can normalize the normal vector with
n /= np.linalg.norm(n) # which should be sqrt(n[0]**2 + n[1]**2 + n[2]**2)
You can then calculate the center point of your input triangle:
pmid = (p1 + p2 + p3) / 3
After that you calculate the distance of the triangle-center to your surface centroid. This is
dist_centroid = np.linalg.norm(pmid - centroid)
The you can calculate the distance of your triangle_center + your normal with the length of the distance to the centroid.
dist_with_normal = np.linalg.norm(pmid + n * dist_centroid - centroid)
If this distance is larger than dist_centroid, then your normal is facing outwards. If it is smaller, it is pointing inwards. If you have a perfect sphere and point towards the centroid, it should almost be zero. This may not be the case for your general surface, but the convexity of the surface should make sure, that this is enough to check for its direction.
if(dist_centroid < dist_with_normal):
n *= -1
Another, nicer option is to use a scalar product.
pmid = (p1 + p2 + p3) / 3
if(np.dot(pmid - centroid, n) < 0):
n *= -1
This checks if your normal and the vector from the mid of your triangle to the centroid have the same direction. If that is not so, change the direction.
I'm trying to come up with a formula to estimate reoccurring times when two orbiting planets will form a target angle. I've made some very important assumptions for the sake of simplicity:
Pretend Kepler's laws do not exist
Pretend the speeds are constant
Pretend both planets are orbiting along the same path
Pretend this path is a circle, NOT an ellipse
Here is a diagram to assist in understanding my challenge (Google Docs):
https://docs.google.com/drawings/d/1Z6ziYEKLgc_tlhvJrC93C91w2R9_IGisf5Z3bw_Cxsg/edit?usp=sharing
I ran a simulation and stored data in a spreadsheet (Google Docs):
https://docs.google.com/spreadsheet/ccc?key=0AgPx8CZl3CNAdGRRTlBUUFpnbGhOdnAwYmtTZWVoVVE&usp=sharing
Using the stored data from the simulation, I was able to determine a way to estimate the FIRST occurrence that two orbiting planets form a specific angle:
Initial State
Planet 1: position=0 degrees; speed=1 degree/day
Planet 2: position=30 degrees; speed=6 degrees/day
Target Angle: 90 degrees
I performed these steps:
Speed Difference: s2 - s1 ; 6 - 1 = 5 degrees / day
Angle Formed: p2 - p1 ; 30 - 0 = 30 degrees
Find Days Required
Target = Angle + (Speed Diff * Days)
Days (d) = (Target - Angle) / Speed Diff
90 = 30 + 5d
60 = 5d
d = 12 days
Prove:
Position of Planet 1: 0 + (1 * 12) = 12 degrees
Position of Planet 2: 30 + (6 * 12) = 30 + 72 + 102 degrees
Angle: 102 - 12 = 90 degrees
Using this logic, I then returned to an astronomy program that uses Astro's Swiss Ephemeris. The estimated days got me close enough to comfortably pinpoint the date and time when two planets reached the desired angle without affecting application performance.
Here is where my problem lies: Given the information that I know, what approach should I take in order to estimate re-occurring times when a 90 degree angle will be reached again?
Thank you for taking the time to read this in advance.
There is not a simple formula as such but there is an algorithm you could program to determine the results. Pentadecagon is also correct in that you need to take into account n*360. You are also right in that you stop one of the planets and work on the difference of the speeds.
After d days the difference in degrees between the planets is 30 + d*5.
Since we are only interested in degrees between 0 and 360 then the difference of the angle between planets is (30 + d*5) mod 360.
In case you do not know a mod b gives the remainder when a is divided by b and most programming languages have this operation built in (as do spreadsheets).
You have spotted you want the values of d when the difference is 90 degrees or 270 degrees
So you need to find the values of d whenever
(30 + d*5) mod 360 = 90 or (30 + d*5) mod 360 = 270
pseudo code algorithm
FOR (d=0; d<11; d=d+5)
IF((30 + d*5) MOD 360 = 90 OR (30 + d*5) MOD 360 = 270)
PRINT d
NEXT
The funny thing about angles is that there are different ways to represent the same angle. So you currently set
Target = 90
One revolution later, the same angle could be written as
Target = 90 + 360 = 450
Or generally, n revolutions later
Target = 90 + n * 360
If you also want the same angle with opposite orientation you can set
Target = -90 + n * 360
If you use solve your equation for each of those target angles, you will find all the events you are looking for.
I am processing a series of points which all have the same Y value, but different X values. I go through the points by incrementing X by one. For example, I might have Y = 50 and X is the integers from -30 to 30. Part of my algorithm involves finding the distance to the origin from each point and then doing further processing.
After profiling, I've found that the sqrt call in the distance calculation is taking a significant amount of my time. Is there an iterative way to calculate the distance?
In other words:
I want to efficiently calculate: r[n] = sqrt(x[n]*x[n] + y*y)). I can save information from the previous iteration. Each iteration changes by incrementing x, so x[n] = x[n-1] + 1. I can not use sqrt or trig functions because they are too slow except at the beginning of each scanline.
I can use approximations as long as they are good enough (less than 0.l% error) and the errors introduced are smooth (I can't bin to a pre-calculated table of approximations).
Additional information:
x and y are always integers between -150 and 150
I'm going to try a couple ideas out tomorrow and mark the best answer based on which is fastest.
Results
I did some timings
Distance formula: 16 ms / iteration
Pete's interperlating solution: 8 ms / iteration
wrang-wrang pre-calculation solution: 8ms / iteration
I was hoping the test would decide between the two, because I like both answers. I'm going to go with Pete's because it uses less memory.
Just to get a feel for it, for your range y = 50, x = 0 gives r = 50 and y = 50, x = +/- 30 gives r ~= 58.3. You want an approximation good for +/- 0.1%, or +/- 0.05 absolute. That's a lot lower accuracy than most library sqrts do.
Two approximate approaches - you calculate r based on interpolating from the previous value, or use a few terms of a suitable series.
Interpolating from previous r
r = ( x2 + y2 ) 1/2
dr/dx = 1/2 . 2x . ( x2 + y2 ) -1/2 = x/r
double r = 50;
for ( int x = 0; x <= 30; ++x ) {
double r_true = Math.sqrt ( 50*50 + x*x );
System.out.printf ( "x: %d r_true: %f r_approx: %f error: %f%%\n", x, r, r_true, 100 * Math.abs ( r_true - r ) / r );
r = r + ( x + 0.5 ) / r;
}
Gives:
x: 0 r_true: 50.000000 r_approx: 50.000000 error: 0.000000%
x: 1 r_true: 50.010000 r_approx: 50.009999 error: 0.000002%
....
x: 29 r_true: 57.825065 r_approx: 57.801384 error: 0.040953%
x: 30 r_true: 58.335225 r_approx: 58.309519 error: 0.044065%
which seems to meet the requirement of 0.1% error, so I didn't bother coding the next one, as it would require quite a bit more calculation steps.
Truncated Series
The taylor series for sqrt ( 1 + x ) for x near zero is
sqrt ( 1 + x ) = 1 + 1/2 x - 1/8 x2 ... + ( - 1 / 2 )n+1 xn
Using r = y sqrt ( 1 + (x/y)2 ) then you're looking for a term t = ( - 1 / 2 )n+1 0.36n with magnitude less that a 0.001, log ( 0.002 ) > n log ( 0.18 ) or n > 3.6, so taking terms to x^4 should be Ok.
Y=10000
Y2=Y*Y
for x=0..Y2 do
D[x]=sqrt(Y2+x*x)
norm(x,y)=
if (y==0) x
else if (x>y) norm(y,x)
else {
s=Y/y
D[round(x*s)]/s
}
If your coordinates are smooth, then the idea can be extended with linear interpolation. For more precision, increase Y.
The idea is that s*(x,y) is on the line y=Y, which you've precomputed distances for. Get the distance, then divide it by s.
I assume you really do need the distance and not its square.
You may also be able to find a general sqrt implementation that sacrifices some accuracy for speed, but I have a hard time imagining that beating what the FPU can do.
By linear interpolation, I mean to change D[round(x)] to:
f=floor(x)
a=x-f
D[f]*(1-a)+D[f+1]*a
This doesn't really answer your question, but may help...
The first questions I would ask would be:
"do I need the sqrt at all?".
"If not, how can I reduce the number of sqrts?"
then yours: "Can I replace the remaining sqrts with a clever calculation?"
So I'd start with:
Do you need the exact radius, or would radius-squared be acceptable? There are fast approximatiosn to sqrt, but probably not accurate enough for your spec.
Can you process the image using mirrored quadrants or eighths? By processing all pixels at the same radius value in a batch, you can reduce the number of calculations by 8x.
Can you precalculate the radius values? You only need a table that is a quarter (or possibly an eighth) of the size of the image you are processing, and the table would only need to be precalculated once and then re-used for many runs of the algorithm.
So clever maths may not be the fastest solution.
Well there's always trying optimize your sqrt, the fastest one I've seen is the old carmack quake 3 sqrt:
http://betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/
That said, since sqrt is non-linear, you're not going to be able to do simple linear interpolation along your line to get your result. The best idea is to use a table lookup since that will give you blazing fast access to the data. And, since you appear to be iterating by whole integers, a table lookup should be exceedingly accurate.
Well, you can mirror around x=0 to start with (you need only compute n>=0, and the dupe those results to corresponding n<0). After that, I'd take a look at using the derivative on sqrt(a^2+b^2) (or the corresponding sin) to take advantage of the constant dx.
If that's not accurate enough, may I point out that this is a pretty good job for SIMD, which will provide you with a reciprocal square root op on both SSE and VMX (and shader model 2).
This is sort of related to a HAKMEM item:
ITEM 149 (Minsky): CIRCLE ALGORITHM
Here is an elegant way to draw almost
circles on a point-plotting display:
NEW X = OLD X - epsilon * OLD Y
NEW Y = OLD Y + epsilon * NEW(!) X
This makes a very round ellipse
centered at the origin with its size
determined by the initial point.
epsilon determines the angular
velocity of the circulating point, and
slightly affects the eccentricity. If
epsilon is a power of 2, then we don't
even need multiplication, let alone
square roots, sines, and cosines! The
"circle" will be perfectly stable
because the points soon become
periodic.
The circle algorithm was invented by
mistake when I tried to save one
register in a display hack! Ben Gurley
had an amazing display hack using only
about six or seven instructions, and
it was a great wonder. But it was
basically line-oriented. It occurred
to me that it would be exciting to
have curves, and I was trying to get a
curve display hack with minimal
instructions.
I have xy co-ordinate like (200,200). I know the angle calculation from the origin the ball throws. How can I find the initial velocity to reach that particular xy co-ordinate when ball is thrown in 2d Environment?
Iam using
x = v0cosq0t;
y = v0sinq0t - (1/2)gt2.
but time is needed. Without time can I do it? any help please?
I'm assuming that you want the ball to hit that specific point (200,200) at the apex of its path. Well, my physics is a bit rusty, but this is what I've thrown together:
v_y = square_root(2*g*y),
where g is a positive number reflecting the acceleration due to gravity, and y being how high you want to go (200 in this case).
v_x = (x*g) / v_y,
where x is how far in the x direction you want to go (200 in this case), g is as before, and Vy is the answer we got in the previous equation.
These equations remove the need for an angle. However, if you'd rather have the velocity + angle, that's simple:
v0 = square_root(v_x^2 + v_y^2)
and
angle = arctan(v_y / v_x).
Here is the derivation, if you're interested:
(1/2)at^2 + v_yt + 0 = y
(1/2)at^2 + v_yt - y = 0
by quadratic formula,
t = (-v_y +/- square_root(v_y^2 - 2ay)) / a
we also have another equation, because at the apex the vertical velocity is 0:
0 = v_y + at
substitute:
0 = v_y + (-v_y +/- square_root(v_y^2 - 2ay))
0 = square_root(v_y^2 - 2ay)
0 = v_y^2 - 2ay
v_y = square_root(-2ay), or
v_y = square_root(2gy)
For v_x:
v_x*t = x
from before, t = v_y / a, so
v_x = (x*g)/v_y
I hope that made enough sense.
Im sure you can assume the velocity change is instantaneous. Games physics always has some 'dodgy' parts in it because it is too computationally expensive or not important enough to get right down the low granularity information.
You can start the velocity ass instantaneous, and then using a timer class to measure then time between each frame (very rough way of doing it), or you can have a timer class set up in an update loop that will update the physics every x seconds.