0

How to calculate the L1 and L2 norm of angle values wrt the ground truths (where Angle values have -180 degrees to 180 degrees period)?

If I have an array of data ip_data[] and an array of ground truth values gt[] then the L1 and L2 norm can be calculated:

L1 norm = sum(abs(gt[i] - ip_data[i]))

L2 norm = sqrt(sum( (gt[i] - ip_data[i])^2 ))

However, generally, in the case of the angle values, they have -180 degrees to 180 degrees period. So, let's say

gt[] = [175, 179, 177]

ip_data_a[] = [165, 169, 167]

ip_data_b[] = [-175, -171, -173]

For ip_data_a[],

L1 = |175 - 165| + |179 - 169| + |177 - 167| = 30
L2 = sqrt(10^2 + 10^2 + 10^2) = sqrt(300)    = 17.32

For ip_data_b[],

L1 = |175 - (-175)| + |179 - (-171)| + |177 - (-173)| = 1050
L2 = sqrt(350^2 + 350^2 + 350^2) = sqrt(367500)       = 606.22

As can be seen, there is a huge difference in L1(or L2) for ip_data_a[] v/s ip_data_b[] even though all the values in both the data array are exactly 10 degrees away from the ground truth except in opposite directions.

Normalizing these angles from [-180, 180] to [0, 360] does not help. Because the same thing will happen when the GT angle is close to 360 deg and the given angle value is close to 0 deg or vice-versa.

So, in this type of scenario/data, what is the correct way of calculating the L1 and L2 norm so that data can be assessed properly?

Milan
  • 1,743
  • 2
  • 13
  • 36
  • that's just arithmetic, right? figure out the proper math so that your signed differences (of target and actual) lie between -180 and +180. that takes some addition and modulo and subtraction. – Christoph Rackwitz Apr 14 '23 at 21:14

1 Answers1

2

It may seem roundabout, but it may be easier to go through the trigonometric functions if confusing to the discontinuous boundary of angle value.
Since the value of sin and cos are continuous, the problem disappears automatically!

That is, solve the angles between the unit vectors. e.g. the angle can be obtained from arc-cosine of inner-product.

Unit vector for angle is [cos(angle), sin(angle)]^T as you know.
cos( a - b ) is inner-product between 2 unit vectors : cos(a)cos(b) + sin(a)sin(b).
So, the "difference" between the two angles a,b is arc-cosine of this.


If you want simple arithmetic way, it will like as below. This returns "L1 norm".

//a and b are angle(degree) and in range [-180, 180].
double DiffAngle( double a, double b )
{
    //Because of the input range constraint, this value can not be greater than 360.
    double Raw = fabs(a-b);  //|a-b|
    //When the above value becomes over 180, desired value will be this.
    double Opposite = 360 - Raw;
    //So what you need is to choose one of them.
    return (std::min)( Raw, Opposite );  //choose smaller one
}
fana
  • 1,370
  • 2
  • 7
  • I think this way is not best but easy. Here, "Easy" means "can avoid some confusion from discontinuous boundary of angle value". – fana Apr 17 '23 at 02:10
  • 1
    I think a modulo operation is quite a bit simpler… – Cris Luengo Apr 17 '23 at 02:27
  • I seems that OP are confusing about such a arithmetics. So, I posted another way which can avoid the confusion. (I already said as "roundabout", "this way is not best") – fana Apr 17 '23 at 02:44
  • My comment was deleted. Now I can't understand what you want. You want to force me to post about the modulo? Why don't by yourself? – fana Apr 18 '23 at 02:46
  • It's just a comment. Don't fret about it. I'm sure your answer will give OP some insight into the problem. – Cris Luengo Apr 18 '23 at 04:19
  • I understand. But now I also added a simple arithmetic method. – fana Apr 18 '23 at 07:03