campreilly / UnderSeaModelingLibrary

The Under Sea Modeling Library (USML) is a collection of C++ software development modules for sonar modeling and simulation.
Other
45 stars 22 forks source link

eigenray_collection::sum_eigenrays() angle weighted averages #216

Closed ellenhp closed 9 years ago

ellenhp commented 9 years ago

I noticed that the way eigenray_collection::sum_eigenrays works takes a weighted average of the azimuth angles of all eigenrays (among other properties). From what I can tell, 2 eigenrays of equal weight and azimuth angles 359 and 1 will average to 180. While this is indeed the mean of the two angles, it isn't useful information to me. The average I'd like to see in that case would be 0.

Is this the expected behavior? If so, is there a way to get the "average" I'm looking for?

campreilly commented 9 years ago

Although it seems to be "working as designed" that behavior is clearly not what we intended. I don't have a ready-made fix in mind for this bug. Do you?

ellenhp commented 9 years ago

I don't have a ready-made fix but I suspect the formula in this stackexchange answer could be modified for a weighted average. I'm not particularly good at this sort of math. I'll let @Tibonium take a shot at it though. Thanks!

campreilly commented 9 years ago

That was along the same train of thought that I was heading. Take a look at this stackexchange answer for a definition of the signed different between any two angles a and b.

d = mod(b - a + 180, 360) - 180

where mod(x,y) is the Euclidean division version of the modulo algorithm

mod(x,y) = x - y * floor( x / y )

and not the truncated division version uses in C++. What I was thinking was:

Example: Three eigenvalues have equal intensity, but AZ arrival angles of 2, 356, 4, and -5.

a = 2;
b = [ 2, 356, 4, -5 ];
d = [ 0, -6, 2, -7 ];
mean(d) = -2.75
mean(b) = a + mean(d) = -0.75 degrees = 358.25 degrees

The issue with the Euclidean vs. truncated only kicks in for negative values of b - a + 180.

Tibonium commented 9 years ago

Consider the instance where b = a. The answer comes to 0. Which is incorrect for all a = b that are not equal to 0 or equal and opposite. As eigenrays tend to be heavily biased in a local azimuth, this would tend to map all averages to roughly 0.

ellenhp commented 9 years ago

Consider the instance where b = a. The answer comes to 0.

Is that correct? Assume the angles 30 and 30.

a = 30; b = [30, 30]; d = [0, 0]; // ((30 - 30 + 180) mod 360) - 180 = 180 - 180 = 0 mean(d) = 0; mean(b) = a + mean(d) = 30 degrees.

I can't think of an edge case for this approach but like I said earlier I'm not the best at this sort of thing.

Tibonium commented 9 years ago

I was commented on the fact that it was incorrect when b=a. I have been working on this and it just so happens that this is the case that I'm currently working to resolve.

ellenhp commented 9 years ago

But the answer comes to a in that case. Like for the 30, 30 case wouldn't the anwser just be 30 as expected? The mean of the signed differences comes to 0, but when you add that to a, you get the correct result, a. Sorry if I'm misunderstanding.

Tibonium commented 9 years ago

Nope, you're correct. The values are then added back to the 'first' value, which I did not account for. I'll continue to look into the equation and other details.

ellenhp commented 9 years ago

Alternatively, a weighted average could be represented as a sum of vectors where the weight is the magnitude of the vector, as described here: http://math.stackexchange.com/a/105779

This seems like it might be a bit easier than trying to modify the algorithm @campreilly posted to incorporate weighting.

campreilly commented 9 years ago

When we figure out how to compute the signed angle difference and signed modulo correctly, we should add them as operations in usml::ublas, like we did for to_degrees().

I know that we'll need them again in other applications. For instance, this discussion. Helped me realize that I have a signed angle difference error in eigenverb overlaps.

Sent from my iPhone 401-523-5780

On May 29, 2015, at 4:10 PM, Nolan Poe notifications@github.com<mailto:notifications@github.com> wrote:

Alternatively, a weighted average could be represented as a sum of vectors where the weight is the magnitude of the vector, as described here: http://math.stackexchange.com/a/105779

This seems like it might be a bit easier than trying to modify the algorithm @campreillyhttps://github.com/campreilly posted to incorporate weighting.

Reply to this email directly or view it on GitHubhttps://github.com/campreilly/UnderSeaModelingLibrary/issues/216#issuecomment-106922652.

The information contained in this message, and any attachments, may contain privileged and/or proprietary information that is intended solely for the person or entity to which it is addressed. Moreover, it may contain export restricted technical data controlled by Export Administration Regulations (EAR) or the International Traffic in Arms Regulations (ITAR). Any review, retransmission, dissemination, or re-export to foreign or domestic entities by anyone other than the intended recipient in accordance with EAR and/or ITAR regulations is prohibited.

ellenhp commented 9 years ago

I'm working on a fix based on a vector sum. Does this problem affect az angles only or de angles as well? I think I'll make my changes in eigenray_collection.cc in my fork and leave it to you guys to merge it upstream however you like.

campreilly commented 9 years ago

DE angles don't have this problem, because they don't wrap around like AZ do.

If you wanted to generate a pull request for your changes changes to eigenray_collection.cc, I think you'd be the first person from the outside to do so, and that could be cool.

ellenhp commented 9 years ago

Ok, I'll do my best to adhere to style, etc. I think I have something (a vector sum isn't particularly hard) but I'll take my time validating it and submit a PR tonight or tomorrow morning.