Calculate coordinates between startpoint and endpoint - algorithm

Given..
1 - The start-point GPS coordinates,
2 - The end-point GPS coordinates,
3 - The speed at which the object is travelling,
4 - Knowing that the trip trajectory will be a straight line...
How can I calculate what my GPS coordinated will be in n minutes' time? That is to say, how can I calculate my position at a given time after the trip has started before the trip has ended?

You need to use the Thaddeus Vincenty Formulae
This will give you the distance between two GPS co-ordinates (lon/lat).
Then simply do
Time = [Distance] in m / [Speed] in m/s
Assuming uniform speed, its a gross estimation.

This method is accurate enough only for small distances, because the curvature of the Earth is not accounted for. You can convert pseudo-spherical coordinates to planar coordinates, but a different method would probably be better for cases where the distance is large and accuracy is needed.
The key is to calculate the total distance between the start and end points. You can use Euclidean distance but, as stated, this is reasonably accurate only for smaller distances:
distance = sqrt((end.x - start.x) ** 2 + (end.y - start.y) ** 2)
You then know how long it will take to travel the entire distance:
timeToTravelDistance = distance / speed
From this, you can calculate the percentage of the distance you have traveled from start to end given time:
percentageTraveled = time / timeToTravelDistance
Finally, interpolate:
result.x = start.x * (1 - percentageTraveled) + end.x * percentageTraveled
result.y = start.y * (1 - percentageTraveled) + end.y * percentageTraveled

Related

Predict Collision Between 2 Uniform Circular Motion Objects

this is my first question on the forum and my algebra is rusty so please be indulgent ^^'
So my problem is that i want to predict collision between two uniform circular motion objects for which i know velocity (angular speed in radian), distance from the origin (radius), cartesian coordinate of the center of the circle.
I can get cartesian position for each object given for t time (timestamp) using :
Oa.x = ra X cos(wa X t)
Oa.y = ra X sin(wa X t)
Oa.x: Object A x coordinates
ra: radius of a Circle A
wa: velocity of object A (angular speed in radian)
t: time (timestamp)
Same goes for object b (Ob)
I want to find t such that ||Ca - Cb|| = (rOa + rOb)
rOa: radius of object a
Squaring both side and expanding give me this :
||Ca-Cb||^2 = (rOa+rOb)^2
(ra * cos (wa * t) - rb / cos (wb * t))^2 + (ra * sin (wa * t) - rb / sin (wb * t))^2 = (ra+rb)^2
From that i should get a quadratic polynomial that i can solve for t, but how can i find a condition that tell me if such a t exist ? And possibly, how to solve it for t ?
Your motion equations are missing some stuff I expect this instead:
a0(t) = omg0*t + ang0
x0(t) = cx0 + R0 * cos(a0(t))
y0(t) = cy0 + R0 * sin(a0(t))
a1(t) = omg1*t + ang1
x1(t) = cx1 + R1 * cos(a1(t))
y1(t) = cy1 + R1 * sin(a1(t))
where t is time in [sec], cx?,cy? is the center of rotation ang? is starting angle (t=0) in [rad] and omg? is angular speed in [rad/sec]. If the objects have radius r? then collision occurs when the distance is <= r0+r1
so You want to find smallest time where:
(x1-x0)^2 + (y1-y0)^2 <= (r0+r1)^2
This will most likely lead to transcendent equation so you need numeric approach to solve this. For stuff like this I usually use Approximation search so to solve this do:
loop t from 0 to some reasonable time limit
The collision will happen with constant frequency and the time between collisions will be divisible by periods of both motions so I would test up to lcm(2*PI/omg0,2*PI/omg1) time limit where lcm is least common multiple
Do not loop t through all possible times with brute force but use heuristic (like the approx search linked above) beware initial time step must be reasonable I would try dt = min(0.2*PI/omg0,0.2*PI/omg1) so you have at least 10 points along circle
solve t so the distance between objects is minimal
This however will find the time when the objects collide fully so their centers merge. So you need to substract some constant time (or search it again) that will get you to the start of collision. This time you can use even binary search as the distance will be monotonic.
next collision will appear after lcm(2*PI/omg0,2*PI/omg1)
so if you found first collision time tc0 then
tc(i) = tc0 + i*lcm(2*PI/omg0,2*PI/omg1)
i = 0,1,2,3,...

Calculate Geolocation on line between two GeoLocations

I have two known Google Geolocation points A and B. I need to return GeoLocation point C which is on AB line and on distance x from point A:
Geolocation returnGeolocationC(Geolocation A, Geolocation B, double x) {
...
return C;
}
I know that I can use Haversine formula and I can calculate AB distance and therefore I also have AC and CB distance. Any idea or hint how to implement this?
Edit: Line is straight, no need to consider roads.
Well, this is a good problem which solution will depend on the area of interest, for instance:
Consider the situation faced by a botanist studying a stand of oak trees on a small plot of land. One component of the data analysis involves determining the location of these trees and calculating the distance betwee
n them. In this situation, straight line or Euclidean distance is the most logical choice. This only requires the use of the Pythagorean Theorem to calculate the shortest distance between two points:
straight_line_distance = sqrt ( ( x2 - x1 )**2 + ( y2 - y1 )**2 );
The variables x and y refer to co-ordinates in a two-dimensional plane and can reflect any unit of measurement, such as feet or miles.
Consider a different situation, an urban area, where the objective is to calculate the distance between customers’ homes and various retail outlets. In this situation, distance takes on a more specific meaning, usually road distance, making straight line distance less suitable. Since streets in many cities are based on a grid system, the typical trip may be approximated by what is known as the Manhattan, city block or taxi cab distance (Fothering-
ham, 2002):
block_distance = ( abs( x2 - x1 ) + abs( y2 - y1 ) ) ;
Instead of the hypotenuse of the right-angled triangle that was calculated for the straight line distance, the above formula simply adds the two sides that form the right angle. The straight line and city block formulae are closely related, and can be generalized by what are referred to as the Minkowski metrics, which in this case are restricted to two dimensions:
minkowski_metric = ( abs(x2 - x1)**k + abs(y2 - y1)**k )**(1/k);
The advantage of this formula is that you only need to vary the exponent to get a range of distance measures. When k = 1, it is equivalent to the city block distance; when k=2, it is the Euclidean distance. Less commonly,
other values of k may be used if desired, usually between 1 and 2. In some situations, it may have been determined that actual distances were greater than the straight line, but less than the city block, in which case a value such as "1.4" may be more appropriate. One of the interesting features of the Minkowski metric is that for values considerably larger than 2 (approaching infinity), the distance is the larger of two sides used in the city block calculation, although this is typically not applicable in a geographic context.
So pseudocode would be something like the following:
distance2d (x1, y1, x2, y2, k)
(max( abs(x2 - x1), abs(y2 - y1) ) * (k > 2))
+
((abs(x2 - x1)**k + abs(y2 - y1)** k )**(1/ k)) * (1 <=k<=2)
end
If 1 <= k <=2, the basic Minkowski metric is applied, since (1 <= k <=2) resolves to 1 and (k > 2) resolves to 0. If k > 2, an alternate formula is applied, since computations become increasingly intensive for large values of k. This second formula is not really necessary, but is useful in demonstrating how modifications can be easily incorporated in distance measures.
The previous distance measures are based on the concept of distance in two dimensions. For small areas like cities or counties, this is a reasonable implification. For longer distances such as those that span larger countries
or continents, measures based on two dimensions are no longer appropriate, since they fail to account for the curvature of the earth. Consequently, global distance measures need to use the graticule, the co-ordinate system
comprised of latitude and longitude along with special formulae to calculate the distances. Lines of latitude run in an east to west direction either above or below the equator. Lines of longitude run north and south through the poles, often with the Prime Meridian (running through Greenwich, England) measured at 0°. Further details of latitude and longitude are available (Slocum et al., 2005). One issue with using latitude and longitude is that the co-ordinates may require some transformation and preparation before they are suitable to use in distance calculations. Coordinates are often expressed in the sexagesimal system (similar to time) of degrees, minutes, and seconds, in which each degree consists of 60 minutes and each
minute is 60 seconds. Furthermore, it is also necessary to provide and indication of the position relative to the equator (North or South) and the Prime Meridian (East or West). The full co-ordinates may take on a variety of formats; below is a typical example that corresponds approximately to the city of Philadelphia:
39° 55' 48" N 75° 12' 12" W
As you mentioned Harvesine, and also I am extending a lot, we can compare results using law of cosines and Harvesine, so pseudocode:
begin
ct = constant('pi')/180 ;
radius = 3959 ; /* 6371 km */
#Both latitude and longitude are in decimal degrees ;
lat1 = 36.12;
long1 = -86.67;
lat2 = 33.94;
long2 = -118.40 ;
#Law of Cosines ;
a = sin(lat1*ct) * sin(lat2*ct) ;
b = cos(lat1*ct) * cos(lat2*ct) * cos((long2-long1) *ct);
c = arcos(a + b) ;
d = radius * c ;
put 'Distance using Law of Cosines ' d
# Haversine ** ;
a2 = sin( ((lat2 - lat1)*ct)/2)**2 +
cos(lat1*ct) * cos(lat2*ct) * sin(((long2 - long1)*ct)/2)**2
c2 = 2 * arsin(min(1,sqrt(a2))) ;
d2 = radius * c2 ;
put 'Distance using Haversine formula =' d2
end
In addition to the constant that will be used to convert degrees to radians, the radius of the earth is required, which on average is equal to 6371 kilometres or 3959 miles. The Law of Cosines uses spherical geometry to
calculate the great circle distance for two points on the globe. The formula is analogous to the Law of Cosines for plane geometry, in which three connected great arcs correspond to the three sides of the triangle. The Haversine formula is mathematically equivalent to the Law of Cosines, but is often preferred since it is less sensitive to round-off error that can occur when measuring distances between points that are located very close tog
ether (Sinnott, 1984). With the Haversine, the error can occur for points that are on opposite sides of the earth, but this is usually less of a problem.
You can find a really easy formula at this link.
Since you have the distance from one of the points and not the fraction of the distance on the segment you can slightly modify the formula:
A=sin(d-x)/sin(d)
B=sin(x)/sin(d)
x = A*cos(lat1)*cos(lon1) + B*cos(lat2)*cos(lon2)
y = A*cos(lat1)*sin(lon1) + B*cos(lat2)*sin(lon2)
z = A*sin(lat1) + B*sin(lat2)
lat=atan2(z,sqrt(x^2+y^2))
lon=atan2(y,x)
where x is the required distance and d is the distance between A and B (that you can evaluate with Haversine), both divided by the Earth radius.
You can also use another formula for sin(d):
nx = cos(lat1)*sin(lon1)*sin(lat2) - sin(lat1)* cos(lat2)*sin(lon2)
ny = -cos(lat1)*cos(lon1)*sin(lat2) + sin(lat1)* cos(lat2)*cos(lon2)
nz = cos(lat1)*cos(lon1)*cos(lat2)*sin(lon2) - cos(lat1)*sin(lon1)*cos(lat2)*cos(lon2)
sind = sqrt(nx^2+ny^2+nz^2)
It's more complex than the Haversine formula, but you can memoize some of the factors in the two steps.
As the OP posted a non working Java implementation, this is my corrections to make it work.
private static GpsLocation CalcGeolocationWithDistance(GpsLocation pointA, GpsLocation pointB, double distanceFromA)
{ //distanceFromA = 2.0 km, PointA and PointB are in Europe on 4.0km distance.
double earthRadius = 6371000.0;
double distanceAB = CalcDistance(pointA.Latitude, pointA.Longitude, pointB.Latitude, pointB.Longitude);
//distance AB is calculated right according to Google Maps (4.0 km)
double a = Math.Sin((distanceAB - distanceFromA) / earthRadius) / Math.Sin(distanceAB / earthRadius);
double b = Math.Sin(distanceFromA / earthRadius) / Math.Sin(distanceAB / earthRadius);
double x = a * Math.Cos(pointA.Latitude * Math.PI / 180) * Math.Cos(pointA.Longitude * Math.PI / 180) + b * Math.Cos(pointB.Latitude * Math.PI / 180) * Math.Cos(pointB.Longitude * Math.PI / 180);
double y = a * Math.Cos(pointA.Latitude * Math.PI / 180) * Math.Sin(pointA.Longitude * Math.PI / 180) + b * Math.Cos(pointB.Latitude * Math.PI / 180) * Math.Sin(pointB.Longitude * Math.PI / 180);
double z = a * Math.Sin(pointA.Latitude * Math.PI / 180) + b * Math.Sin(pointB.Latitude * Math.PI / 180);
double lat = Math.Atan2(z, Math.Sqrt(x * x + y * y)) * 180 / Math.PI;
double lon = Math.Atan2(y, x) * 180 / Math.PI;
//lat and lon are mo more placed somewhere in Africa ;)
return new GpsLocation(lat, lon);
}

Compute equidistant GPS point around a center

I have a question about some GPS calculations.
My problem is as follow :
I have a specific point P, and I want to compute N points around P.
Here is the algorithm :
P = (x, y) // latitude, longitude
N = 8
angle_size = 360/N
points = []
for i in 1..N
points.push compute_100meter(P, angle_size*i)
end
In this example, I'm trying to compute 8 equidistant point within 100 meter from P.
Is anyone know a ruby gem allowing me to do so ?
My problem is to write the content of compute_100meter
EDIT:
I have to take into account the earth curvature and get the point coordinates in degree (latitude, longitude).
As long as the radius is small enough (and 100 meters should be, unless you're right next to the north or south pole), a simple linear approximation should do well enough:
def perimeter_point(lat, lon, angle, radius)
# convert angle from degrees to radians
angle *= Math::PI / 180
# convert meters to degrees approximately, assuming spherical Earth
radius /= 6371000 * Math::PI / 180
# calculate relative length of the circle of longitude compared to equator
scale = Math.cos( lat * Math::PI / 180 );
# add offsets to longitude and latitude and return them
# (I'm assuming that angle = 0 means due east)
lat += radius * Math.sin(angle)
lon += radius * Math.cos(angle) / scale
return lat, lon
end
Note that, if your center point is near the 180th meridian, this could return longitudes below -180 or above +180. If that's a problem, check for it and normalize as needed. (Output latitudes outside the &pm;90 range are also technically possible, if the center point is near the north or south pole, but the approximation I used breaks down close to the poles anyway.)

Averaging angles... Again

I want to calculate the average of a set of angles, which represents source bearing (0 to 360 deg) - (similar to wind-direction)
I know it has been discussed before (several times). The accepted answer was Compute unit vectors from the angles and take the angle of their average.
However this answer defines the average in a non intuitive way. The average of 0, 0 and 90 will be atan( (sin(0)+sin(0)+sin(90)) / (cos(0)+cos(0)+cos(90)) ) = atan(1/2)= 26.56 deg
I would expect the average of 0, 0 and 90 to be 30 degrees.
So I think it is fair to ask the question again: How would you calculate the average, so such examples will give the intuitive expected answer.
Edit 2014:
After asking this question, I've posted an article on CodeProject which offers a thorough analysis. The article examines the following reference problems:
Given time-of-day [00:00-24:00) for each birth occurred in US in the year 2000 - Calculate the mean birth time-of-day
Given a multiset of direction measurements from a stationary transmitter to a stationary receiver, using a measurement technique with a wrapped normal distributed error – Estimate the direction.
Given a multiset of azimuth estimates between two points, made by “ordinary” humans (assuming to subject to a wrapped truncated normal distributed error) – Estimate the direction.
[Note the OP's question (but not title) appears to have changed to a rather specialised question ("...the average of a SEQUENCE of angles where each successive addition does not differ from the running mean by more than a specified amount." ) - see #MaR comment and mine. My following answer addresses the OP's title and the bulk of the discussion and answers related to it.]
This is not a question of logic or intuition, but of definition. This has been discussed on SO before without any real consensus. Angles should be defined within a range (which might be -PI to +PI, or 0 to 2*PI or might be -Inf to +Inf. The answers will be different in each case.
The word "angle" causes confusion as it means different things. The angle of view is an unsigned quantity (and is normally PI > theta > 0. In that cases "normal" averages might be useful. Angle of rotation (e.g. total rotation if an ice skater) might or might not be signed and might include theta > 2PI and theta < -2PI.
What is defined here is angle = direction whihch requires vectors. If you use the word "direction" instead of "angle" you will have captured the OP's (apparent original) intention and it will help to move away from scalar quantities.
Wikipedia shows the correct approach when angles are defined circularly such that
theta = theta+2*PI*N = theta-2*PI*N
The answer for the mean is NOT a scalar but a vector. The OP may not feel this is intuitive but it is the only useful correct approach. We cannot redefine the square root of -4 to be -2 because it's more initutive - it has to be +-2*i. Similarly the average of bearings -90 degrees and +90 degrees is a vector of zero length, not 0.0 degrees.
Wikipedia (http://en.wikipedia.org/wiki/Mean_of_circular_quantities) has a special section and states (The equations are LaTeX and can be seen rendered in Wikipedia):
Most of the usual means fail on
circular quantities, like angles,
daytimes, fractional parts of real
numbers. For those quantities you need
a mean of circular quantities.
Since the arithmetic mean is not
effective for angles, the following
method can be used to obtain both a
mean value and measure for the
variance of the angles:
Convert all angles to corresponding
points on the unit circle, e.g., α to
(cosα,sinα). That is convert polar
coordinates to Cartesian coordinates.
Then compute the arithmetic mean of
these points. The resulting point will
lie on the unit disk. Convert that
point back to polar coordinates. The
angle is a reasonable mean of the
input angles. The resulting radius
will be 1 if all angles are equal. If
the angles are uniformly distributed
on the circle, then the resulting
radius will be 0, and there is no
circular mean. In other words, the
radius measures the concentration of
the angles.
Given the angles
\alpha_1,\dots,\alpha_n the mean is
computed by
M \alpha = \operatorname{atan2}\left(\frac{1}{n}\cdot\sum_{j=1}^n
\sin\alpha_j,
\frac{1}{n}\cdot\sum_{j=1}^n
\cos\alpha_j\right)
using the atan2 variant of the
arctangent function, or
M \alpha = \arg\left(\frac{1}{n}\cdot\sum_{j=1}^n
\exp(i\cdot\alpha_j)\right)
using complex numbers.
Note that in the OP's question an angle of 0 is purely arbitrary - there is nothing special about wind coming from 0 as opposed to 180 (except in this hemisphere it's colder on the bicycle). Try changing 0,0,90 to 289, 289, 379 and see how the simple arithmetic no longer works.
(There are some distributions where angles of 0 and PI have special significance but they are not in scope here).
Here are some intense previous discussions which mirror the current spread of views :-)
Link
How do you calculate the average of a set of circular data?
http://forums.xkcd.com/viewtopic.php?f=17&t=22435
http://www.allegro.cc/forums/thread/595008
Thank you all for helping me see my problem more clearly.
I found what I was looking for.
It is called Mitsuta method.
The inputs and output are in the range [0..360).
This method is good for averaging data that was sampled using constant sampling intervals.
The method assumes that the difference between successive samples is less than 180 degrees (which means that if we won't sample fast enough, a 330 degrees change in the sampled signal would be incorrectly detected as a 30 degrees change in the other direction and will insert an error into the calculation). Nyquist–Shannon sampling theorem anybody ?
Here is a c++ code:
double AngAvrg(const vector<double>& Ang)
{
vector<double>::const_iterator iter= Ang.begin();
double fD = *iter;
double fSigD= *iter;
while (++iter != Ang.end())
{
double fDelta= *iter - fD;
if (fDelta < -180.) fD+= fDelta + 360.;
else if (fDelta > 180.) fD+= fDelta - 360.;
else fD+= fDelta ;
fSigD+= fD;
}
double fAvrg= fSigD / Ang.size();
if (fAvrg >= 360.) return fAvrg -360.;
if (fAvrg < 0. ) return fAvrg +360.;
return fAvrg ;
}
It is explained on page 51 of Meteorological Monitoring Guidance for Regulatory Modeling Applications (PDF)(171 pp, 02-01-2000, 454-R-99-005)
Thank you MaR for sending the link as a comment.
If the sampled data is constant, but our sampling device has an inaccuracy with a Von Mises distribution, a unit-vectors calculation will be appropriate.
This is incorrect on every level.
Vectors add according to the rules of vector addition. The "intuitive, expected" answer might not be that intuitive.
Take the following example. If I have one unit vector (1, 0), with origin at (0,0) that points in the +x-direction and another (-1, 0) that also has its origin at (0,0) that points in the -x-direction, what should the "average" angle be?
If I simply add the angles and divide by two, I can argue that the "average" is either +90 or -90. Which one do you think it should be?
If I add the vectors according to the rules of vector addition (component by component), I get the following:
(1, 0) + (-1, 0) = (0, 0)
In polar coordinates, that's a vector with zero magnitude and angle zero.
So what should the "average" angle be? I've got three different answers here for a simple case.
I think the answer is that vectors don't obey the same intuition that numbers do, because they have both magnitude and direction. Maybe you should describe what problem you're solving a bit better.
Whatever solution you decide on, I'd advise you to base it on vectors. It'll always be correct that way.
What does it even mean to average source bearings? Start by answering that question, and you'll get closer to being to define what you mean by the average of angles.
In my mind, an angle with tangent equal to 1/2 is the right answer. If I have a unit force pushing me in the direction of the vector (1, 0), another force pushing me in the direction of the vector (1, 0) and third force pushing me in the direction of the vector (0, 1), then the resulting force (the sum of these forces) is the force pushing me in the direction of (1, 2). These the the vectors representing the bearings 0 degrees, 0 degrees and 90 degrees. The angle represented by the vector (1, 2) has tangent equal to 1/2.
Responding to your second edit:
Let's say that we are measuring wind direction. Our 3 measurements were 0, 0, and 90 degrees. Since all measurements are equivalently reliable, why shouldn't our best estimate of the wind direction be 30 degrees? setting it to 25.56 degrees is a bias toward 0...
Okay, here's an issue. The unit vector with angle 0 doesn't have the same mathematical properties that the real number 0 has. Using the notation 0v to represent the vector with angle 0, note that
0v + 0v = 0v
is false but
0 + 0 = 0
is true for real numbers. So if 0v represents wind with unit speed and angle 0, then 0v + 0v is wind with double unit speed and angle 0. And then if we have a third wind vector (which I'll representing using the notation 90v) which has angle 90 and unit speed, then the wind that results from the sum of these vectors does have a bias because it's traveling at twice unit speed in the horizontal direction but only unit speed in the vertical direction.
In my opinion, this is about angles, not vectors. For that reason the average of 360 and 0 is truly 180.
The average of one turn and no turns should be half a turn.
Edit: Equivalent, but more robust algorithm (and simpler):
divide angles into 2 groups, [0-180) and [180-360)
numerically average both groups
average the 2 group averages with proper weighting
if wraparound occurred, correct by 180˚
This works because number averaging works "logically" if all the angles are in the same hemicircle. We then delay getting wraparound error until the very last step, where it is easily detected and corrected. I also threw in some code for handling opposite angle cases. If the averages are opposite we favor the hemisphere that had more angles in it, and in the case of equal angles in both hemispheres we return None because no average would make sense.
The new code:
def averageAngles2(angles):
newAngles = [a % 360 for a in angles];
smallAngles = []
largeAngles = []
# split the angles into 2 groups: [0-180) and [180-360)
for angle in newAngles:
if angle < 180:
smallAngles.append(angle)
else:
largeAngles.append(angle)
smallCount = len(smallAngles)
largeCount = len(largeAngles)
#averaging each of the groups will work with standard averages
smallAverage = sum(smallAngles) / float(smallCount) if smallCount else 0
largeAverage = sum(largeAngles) / float(largeCount) if largeCount else 0
if smallCount == 0:
return largeAverage
if largeCount == 0:
return smallAverage
average = (smallAverage * smallCount + largeAverage * largeCount) / \
float(smallCount + largeCount)
if largeAverage < smallAverage + 180:
# average will not hit wraparound
return average
elif largeAverage > smallAverage + 180:
# average will hit wraparound, so will be off by 180 degrees
return (average + 180) % 360
else:
# opposite angles: return whichever has more weight
if smallCount > largeCount:
return smallAverage
elif smallCount < largeCount:
return largeAverage
else:
return None
>>> averageAngles2([0, 0, 90])
30.0
>>> averageAngles2([30, 350])
10.0
>>> averageAngles2([0, 200])
280.0
Here's a slightly naive algorithm:
remove all oposite angles from the list
take a pair of angles
rotate them to the first and second quadrant and average them
rotate average angle back by same amount
for each remaining angle, average in same way, but with successively increasing weight to the composite angle
some python code (step 1 not implemented)
def averageAngles(angles):
newAngles = [a % 360 for a in angles];
average = 0
weight = 0
for ang in newAngles:
theta = 0
if 0 < ang - average <= 180:
theta = 180 - ang
else:
theta = 180 - average
r_ang = (ang + theta) % 360
r_avg = (average + theta) % 360
average = ((r_avg * weight + r_ang) / float(weight + 1) - theta) % 360
weight += 1
return average
Here's the answer I gave to this same question:
How do you calculate the average of a set of circular data?
It gives answers inline with what the OP says he wants, but attention should be paid to this:
"I would also like to stress that even though this is a true average of angles, unlike the vector solutions, that does not necessarily mean it is the solution you should be using, the average of the corresponding unit vectors may well be the value you actually should to be using."
You are correct that the accepted answer of using traditional average is wrong.
An average of a set of points x_1 ... x_n in a metric space X is an element x in X that minimizes the sum of distances squares to each point (See Frechet mean). If you try to find this minimum using simple calculus with regular real numbers, you will recover the standard "add up and divide by n" formula.
For an angle, our elements are actually points on the unit circle S1. Our metric isn't euclidean distance, but arc length, which is proportional to angle.
So, the average angle is the one that minimizes the square of the angle difference between each other angle. In other words,
if you have a function angleBetween(a, b) you want to find the angle a
such that sum over i of angleBetween(a_i, a) is minimized.
This is an optimization problem which can be solved using a numerical optimizer. Several of the answers here claim to provide simpler closed forms, or at least better approximations.
Statistics
As you point out in your article, you need to assume errors follow a Gaussian distribution to justify using least squares as the maximum likelyhood estimator. So in this application, where is the error? Is the random error in the position of two things, and the angle is just the normal of the line between them? If so, that normal will not follow a Gaussian distribution, even if the error in point position does. Taking means of angles only really makes sense if the random error is observed in the angle itself.
You could do this: Say you have a set of angles in an array angle, then to compute the array first do: angle[i] = angle[i] mod 360, now perform a simple average over the array. So when you have 360, 10, 20, you are averaging 0, 10 and 20 - the results are intuitive.
What is wrong with taking the set of angles as real values and just computing the arithmetic average of those numbers? Then you would get the intuitive (0+0+90)/3 = 30 deg.
Edit: Thanks for useful comments and pointing out that angles may exceed 360. I believe the answer could be the normal arithmetic average reduced "modulo" 360: we sum all the values, divide by the number of angles and then subtract/add a multiple of 360 so that the result lies in the interval [0..360).
I think the problem stems from how you treat angles greater than 180 (and those greater than 360 as well). If you reduce the angles to a range of +180 to -180 before adding them to the total, you get something more reasonable:
int AverageOfAngles(int angles[], int count)
{
int total = 0;
for (int index = 0; index < count; index++)
{
int angle = angles[index] % 360;
if (angle > 180) { angle -= 360; }
total += angle;
}
return (int)((float)total/count);
}
Maybe you could represent angles as quaternions and take average of these quaternions and convert it back to angle.
I don't know If it gives you what you want because quaternions are rather rotations than angles. I also don't know if it will give you anything different from vector solution.
Quaternions in 2D simplify to complex numbers so I guess It's just vectors but maybe some interesting quaternion averaging algorithm like http://ntrs.nasa.gov/archive/nasa/casi.ntrs.nasa.gov/20070017872_2007014421.pdf when simplified to 2D will behave better than just vector average.
Here you go! The reference is https://www.wxforum.net/index.php?topic=8660.0
def avgWind(directions):
sinSum = 0
cosSum = 0
d2r = math.pi/180 #degree to radian
r2d = 180/math.pi
for i in range(len(directions)):
sinSum += math.sin(directions[i]*d2r)
cosSum += math.cos(directions[i]*d2r)
return ((r2d*(math.atan2(sinSum, cosSum)) + 360) % 360)
a= np.random.randint(low=0, high=360, size=6)
print(a)
avgWind(a)

circle-circle collision

I am going to develop a 2-d ball game where two balls (circles) collide. Now I have the problem with determining the colliding point (in fact, determining whether they are colliding in x-axis/y-axis). I have an idea that when the difference between the y coordinate of 2 balls is greater than the x coordinate difference then they collide in their y axis, otherwise, they collide in their x axis. Is my idea correct? I implemented this thing in my games. Normally it works well, but sometimes, it fails. Can anyone tell me whether my idea is right? If not, then why, and is any better way?
By collision in the x axis, I mean the circle's 1st, 4th, 5th, or 8th octant, y axis means the circle's 2nd, 3rd, 6th, or 7th octant.
Thanks in advance!
Collision between circles is easy. Imagine there are two circles:
C1 with center (x1,y1) and radius r1;
C2 with center (x2,y2) and radius r2.
Imagine there is a line running between those two center points. The distance from the center points to the edge of either circle is, by definition, equal to their respective radii. So:
if the edges of the circles touch, the distance between the centers is r1+r2;
any greater distance and the circles don't touch or collide; and
any less and then do collide.
So you can detect collision if:
(x2-x1)^2 + (y2-y1)^2 <= (r1+r2)^2
meaning the distance between the center points is less than the sum of the radii.
The same principle can be applied to detecting collisions between spheres in three dimensions.
Edit: if you want to calculate the point of collision, some basic trigonometry can do that. You have a triangle:
(x1,y1)
|\
| \
| \ sqrt((x2-x1)^2 + (y2-y1)^2) = r1+r2
|y2-y1| | \
| \
| X \
(x1,y2) +------+ (x2,y2)
|x2-x1|
The expressions |x2-x1| and |y2-y1| are absolute values. So for the angle X:
|y2 - y1|
sin X = -------
r1 + r2
|x2 - x1|
cos X = -------
r1 + r2
|y2 - y1|
tan X = -------
|x2 - x1|
Once you have the angle you can calculate the point of intersection by applying them to a new triangle:
+
|\
| \
b | \ r2
| \
| X \
+-----+
a
where:
a
cos X = --
r2
so
a = r2 cos X
From the previous formulae:
|x2 - x1|
a = r2 -------
r1 + r2
Once you have a and b you can calculate the collision point in terms of (x2,y2) offset by (a,b) as appropriate. You don't even need to calculate any sines, cosines or inverse sines or cosines for this. Or any square roots for that matter. So it's fast.
But if you don't need an exact angle or point of collision and just want the octant you can optimize this further by understanding something about tangents, which is:
0 <= tan X <= 1 for 0 <= X <= 45 degrees;
tan X >= 1 for 45 <= X <= 90
0 >= tan X >= -1 for 0 >= X => -45;
tan X <= -1 for -45 >= X => -90; and
tan X = tan (X+180) = tan (X-180).
Those four degree ranges correspond to four octants of the cirlce. The other four are offset by 180 degrees. As demonstrated above, the tangent can be calculated simply as:
|y2 - y1|
tan X = -------
|x2 - x1|
Lose the absolute values and this ratio will tell you which of the four octants the collision is in (by the above tangent ranges). To work out the exact octant just compare x1 and x2 to determine which is leftmost.
The octant of the collision on the other single is offset (octant 1 on C1 means octant 5 on C2, 2 and 6, 3 and 7, 4 and 8, etc).
As cletus says, you want to use the sum of the radii of the two balls. You want to compute the total distance between the centers of the balls, as follows:
Ball 1: center: p1=(x1,y1) radius: r1
Ball 2: center: p2=(x2,y2) radius: r2
collision distance: R= r1 + r2
actual distance: r12= sqrt( (x2-x1)^2 + (y2-y1)^2 )
A collision will happen whenever (r12 < R). As Artelius says, they shouldn't actually collide on the x/y axes, they collide at a particular angle. Except, you don't actually want that angle; you want the collision vector. This is the difference between the centers of the two circles when they collide:
collision vector: d12= (x2-x1,y2-y1) = (dx,dy)
actual distance: r12= sqrt( dx*dx + dy*dy )
Note that you have already computed dx and dy above when figuring the actual distance, so you might as well keep track of them for purposes like this. You can use this collision vector for determining the new velocity of the balls -- you're going to end up scaling the collision vector by some factors, and adding that to the old velocities... but, to get back to the actual collision point:
collision point: pcollision= ( (x1*r2+x2*r1)/(r1+r2), (y1*r2+y2*r1)/(r1+r2) )
To figure out how to find the new velocity of the balls (and in general to make more sense out of the whole situation), you should probably find a high school physics book, or the equivalent. Unfortunately, I don't know of a good web tutorial -- suggestions, anyone?
Oh, and if still want to stick with the x/y axis thing, I think you've got it right with:
if( abs(dx) > abs(dy) ) then { x-axis } else { y-axis }
As for why it might fail, it's hard to tell without more information, but you might have a problem with your balls moving too fast, and passing right by each other in a single timestep. There are ways to fix this problem, but the simplest way is to make sure they don't move too fast...
This site explains the physics, derives the algorithm, and provides code for collisions of 2D balls.
Calculate the octant after this function calculates the following: position of collision point relative to centre of mass of body a; position of collision point relative to centre of mass of body a
/**
This function calulates the velocities after a 2D collision vaf, vbf, waf and wbf from information about the colliding bodies
#param double e coefficient of restitution which depends on the nature of the two colliding materials
#param double ma total mass of body a
#param double mb total mass of body b
#param double Ia inertia for body a.
#param double Ib inertia for body b.
#param vector ra position of collision point relative to centre of mass of body a in absolute coordinates (if this is
known in local body coordinates it must be converted before this is called).
#param vector rb position of collision point relative to centre of mass of body b in absolute coordinates (if this is
known in local body coordinates it must be converted before this is called).
#param vector n normal to collision point, the line along which the impulse acts.
#param vector vai initial velocity of centre of mass on object a
#param vector vbi initial velocity of centre of mass on object b
#param vector wai initial angular velocity of object a
#param vector wbi initial angular velocity of object b
#param vector vaf final velocity of centre of mass on object a
#param vector vbf final velocity of centre of mass on object a
#param vector waf final angular velocity of object a
#param vector wbf final angular velocity of object b
*/
CollisionResponce(double e,double ma,double mb,matrix Ia,matrix Ib,vector ra,vector rb,vector n,
vector vai, vector vbi, vector wai, vector wbi, vector vaf, vector vbf, vector waf, vector wbf) {
double k=1/(ma*ma)+ 2/(ma*mb) +1/(mb*mb) - ra.x*ra.x/(ma*Ia) - rb.x*rb.x/(ma*Ib) - ra.y*ra.y/(ma*Ia)
- ra.y*ra.y/(mb*Ia) - ra.x*ra.x/(mb*Ia) - rb.x*rb.x/(mb*Ib) - rb.y*rb.y/(ma*Ib)
- rb.y*rb.y/(mb*Ib) + ra.y*ra.y*rb.x*rb.x/(Ia*Ib) + ra.x*ra.x*rb.y*rb.y/(Ia*Ib) - 2*ra.x*ra.y*rb.x*rb.y/(Ia*Ib);
double Jx = (e+1)/k * (Vai.x - Vbi.x)( 1/ma - ra.x*ra.x/Ia + 1/mb - rb.x*rb.x/Ib)
- (e+1)/k * (Vai.y - Vbi.y) (ra.x*ra.y / Ia + rb.x*rb.y / Ib);
double Jy = - (e+1)/k * (Vai.x - Vbi.x) (ra.x*ra.y / Ia + rb.x*rb.y / Ib)
+ (e+1)/k * (Vai.y - Vbi.y) ( 1/ma - ra.y*ra.y/Ia + 1/mb - rb.y*rb.y/Ib);
Vaf.x = Vai.x - Jx/Ma;
Vaf.y = Vai.y - Jy/Ma;
Vbf.x = Vbi.x - Jx/Mb;
Vbf.y = Vbi.y - Jy/Mb;
waf.x = wai.x - (Jx*ra.y - Jy*ra.x) /Ia;
waf.y = wai.y - (Jx*ra.y - Jy*ra.x) /Ia;
wbf.x = wbi.x - (Jx*rb.y - Jy*rb.x) /Ib;
wbf.y = wbi.y - (Jx*rb.y - Jy*rb.x) /Ib;
}
I agree with provided answers, they are very good.
I just want to point you a small pitfall: if the speed of balls is high, you can just miss the collision, because circles never intersect for given steps.
The solution is to solve the equation on the movement and to find the correct moment of the collision.
Anyway, if you would implement your solution (comparisons on X and Y axes) you'd get the good old ping pong! http://en.wikipedia.org/wiki/Pong
:)
The point at which they collide is on the line between the midpoints of the two circles, and its distance from either midpoint is the radius of that respective circle.

Resources