SRL Archive - SRL Bugs

New rs_GetCompassAngle


ReadySteadyGo

2011-11-23 16:44:53

(* start math.simba additions *)
type
TVector = record
a: Extended;
b: Extended;
Magnitude: Extended;
end;


function fixRad(rad: Extended): Extended; // by Nava2
var
math_2pi: Extended;
begin
math_2pi := 2*pi;
result := rad;

while (result >= math_2pi) do
result := result - math_2pi;

while (result < 0) do
result := result + math_2pi;
end;

function AngleBetween(v1, v2: TVector): Extended;
var
a1, a2: Extended;
begin
a1 := ArcTan2(v1.b, v1.a);
a2 := ArcTan2(v2.b, v2.a);

Result := fixRad(a1 - a2)
end;


procedure Normalise(var vect: TVector);
begin
vect.a := vect.a / vect.Magnitude;
vect.b := vect.b / vect.Magnitude;
vect.Magnitude := 1;
end;

function CreateVector(Origin, vPoint: TPoint; NormaliseV: Boolean): TVector;
begin
Result.a := vPoint.x - Origin.x;
Result.b := 0 - (vPoint.y - Origin.y); // inverts y axis as well
Result.Magnitude := Sqrt(Sqr(Result.a) + Sqr(Result.b));
if NormaliseV then
Normalise(Result);
end;

(* end math.simba additions *)

function rs_GetCompassAngleRadians: Extended;
var
tpa: TPointArray;
atpa: T2DPointArray;
i, h, l: Integer;
VectorArray: Array of TVector;
RefPoint: TPoint;
angles: TExtendedArray;
math_2pi: Extended;
begin
math_2pi := 2*pi;

{ Colour of 3 E/S/W dots }
FindColorsTolerance(tpa, 2239277, 529, 9, 558, 39, 0);

atpa := SplitTPA(tpa, 1);

h := High(atpa);
setLength(tpa, h+1);
l := 0;
for i := 0 to h do
{ Gets rid of dots under length of 3 and get the MiddleTPA }
if high(atpa[i]) > 4 then
begin
tpa[l] := MiddleTPA(atpa[i]);
inc(l);
end;

if l < 3 then
Exit;

setLength(tpa, l);

SetLength(VectorArray, 3);

for i := 0 to 2 do
VectorArray[i] := CreateVector(Point(543, 24), tpa[i], True);

angles := [AngleBetween(VectorArray[0], VectorArray[1]),
AngleBetween(VectorArray[1], VectorArray[2]),
AngleBetween(VectorArray[2], VectorArray[0])];

for i := 0 to 2 do
begin
if angles[i] > pi then
angles[i] := math_2pi - angles[i];
{ compare angle between, > 100 then it's the south dot }
if angles[i] > radians(100) then
begin
case i of
0: RefPoint := tpa[2];
1: RefPoint := tpa[0];
2: RefPoint := tpa[1];
end;
{ break the loop, we have reference pt. }
break;
end;
end;


{ Using the south dot to measure compass angle.. }
Result := ArcTan2(-(RefPoint.Y - 24), RefPoint.X - 543) - Radians(80);
Result := fixRad(Result - Pi - 0.05*Pi);
end;

function rs_GetCompassAngleDegrees: Extended;
begin
Result := Degrees(rs_GetCompassAngleRadians());
end;

I made a new thread as the other one was apparently resolved. Unfortunately, the rs_GetCompassAngle was very inaccurate, so I have written a new one.

Edit: Corrected to anticlockwise
Edit: Made Nava2's suggested changes

euphemism

2011-11-23 18:16:01

ReadySteadyGo, it seems to work rather well. Much more accurate than the fix that was implemented.

Nava2

2011-11-23 18:59:57

My question.. why do things in terms of degrees when you are working with radians?

Also, what do A and B represent in the vector..? Are those x, y respectively?

Is the TPA always of length 3? If not, you may get out of range errors.

You also set refpoint multiple times. Should that case be broken out of?

Pleeeeeease comment your code a bit more so we know whats going on.. :(

ReadySteadyGo

2011-11-23 20:22:02

From: Nava2
My question.. why do things in terms of degrees when you are working with radians?

Also, what do A and B represent in the vector..? Are those x, y respectively?

Is the TPA always of length 3? If not, you may get out of range errors.

You also set refpoint multiple times. Should that case be broken out of?

Pleeeeeease comment your code a bit more so we know whats going on.. :(


Ok. I am measuring the angles between the 3 dots on the compass to get the south one for an accurate compass angle measuring point. The TPA is always 3 because there are only three dots. However Coh3n suggested I add some sort of fail safe in case of an RS update. Also, it only sets RefPoint once because only one of the comparisons has an angle thats > 100.

Yes, a and b could be x and y.

I'll make a couple of changes.

Changed opening post

Nava2

2011-11-23 21:01:13

(* start math.simba additions *)
type
TVector = record
a: Extended;
b: Extended;
Magnitude: Extended;
end;

const
math_2pi = 2*pi;

function fixRad(rad: Extended): Extended; // by Nava2
begin
result := rad;

while (result >= math_2pi) do
result := result - math_2pi;

while (result < 0) do
result := result + math_2pi;
end;

function AngleBetween(v1, v2: TVector): Extended;
var
a1, a2: Extended;
begin
a1 := ArcTan2(v1.b, v1.a);
a2 := ArcTan2(v2.b, v2.a);

Result := fixRad(a1 - a2)
end;


procedure Normalise(var vect: TVector);
begin
vect.a := vect.a / vect.Magnitude;
vect.b := vect.b / vect.Magnitude;
vect.Magnitude := 1;
end;

function CreateVector(Origin, vPoint: TPoint; NormaliseV: Boolean): TVector;
begin
Result.a := vPoint.x - Origin.x;
Result.b := 0 - (vPoint.y - Origin.y); // inverts y axis as well
Result.Magnitude := Sqrt(Sqr(Result.a) + Sqr(Result.b));
if NormaliseV then
Normalise(Result);
end;

(* end math.simba additions *)

function rs_GetCompassAngleRadians: Extended;
var
tpa: TPointArray;
atpa: T2DPointArray;
i, h: Integer;
VectorArray: Array of TVector;
RefPoint: TPoint;
angles: TExtendedArray;
begin
{ Colour of 3 E/S/W dots }
FindColorsTolerance(tpa, 2239277, 529, 9, 558, 39, 0);

atpa := SplitTPA(tpa, 1);
setLength(TPA, 3);

h := High(atpa);
for i := 0 to h do
{ Gets rid of dots under length of 3 and get the MiddleTPA }
if high(atpa[i]) > 4 then
tpa[l] := MiddleTPA(atpa[i]);

SetLength(VectorArray, 3);

for i := 0 to 2 do
VectorArray[i] := CreateVector(Point(543, 24), tpa[i], True);

angles := [AngleBetween(VectorArray[0], VectorArray[1]),
AngleBetween(VectorArray[1], VectorArray[2]),
AngleBetween(VectorArray[2], VectorArray[0])];

for i := 0 to 2 do
begin
if angles[i] > pi then
angles[i] := math_2pi - angles[i];
{ compare angle between, > 100 then it's the south dot }
if angles[i] > radians(100) then
begin
case i of
0: RefPoint := tpa[2];
1: RefPoint := tpa[0];
2: RefPoint := tpa[1];
end;
{ break the loop, we have reference pt. }
break;
end;
end;


{ Using the south dot to measure compass angle.. }
Result := ArcTan2(-(RefPoint.Y - 24), RefPoint.X - 543) - Radians(80);
Result := fixRad(Result - Pi - 0.05*Pi);
end;

function rs_GetCompassAngleDegrees: Extended;
begin
Result := Degrees(rs_GetCompassAngleRadians());
end;

ReadySteadyGo

2011-11-23 21:50:25

(* start math.simba additions *)
type
TVector = record
a: Extended;
b: Extended;
Magnitude: Extended;
end;


function fixRad(rad: Extended): Extended; // by Nava2
var
math_2pi: Extended;
begin
math_2pi := 2*pi;
result := rad;

while (result >= math_2pi) do
result := result - math_2pi;

while (result < 0) do
result := result + math_2pi;
end;

function AngleBetween(v1, v2: TVector): Extended;
var
a1, a2: Extended;
begin
a1 := ArcTan2(v1.b, v1.a);
a2 := ArcTan2(v2.b, v2.a);

Result := fixRad(a1 - a2)
end;


procedure Normalise(var vect: TVector);
begin
vect.a := vect.a / vect.Magnitude;
vect.b := vect.b / vect.Magnitude;
vect.Magnitude := 1;
end;

function CreateVector(Origin, vPoint: TPoint; NormaliseV: Boolean): TVector;
begin
Result.a := vPoint.x - Origin.x;
Result.b := 0 - (vPoint.y - Origin.y); // inverts y axis as well
Result.Magnitude := Sqrt(Sqr(Result.a) + Sqr(Result.b));
if NormaliseV then
Normalise(Result);
end;

(* end math.simba additions *)

function rs_GetCompassAngleRadians: Extended;
var
tpa: TPointArray;
atpa: T2DPointArray;
i, h, l: Integer;
VectorArray: Array of TVector;
RefPoint: TPoint;
angles: TExtendedArray;
math_2pi: Extended;
begin
math_2pi := 2*pi;

{ Colour of 3 E/S/W dots }
FindColorsTolerance(tpa, 2239277, 529, 9, 558, 39, 0);

atpa := SplitTPA(tpa, 1);
SetLength(TPA, 0);

h := High(atpa);
for i := 0 to h do
{ Gets rid of dots under length of 3 and get the MiddleTPA }
if high(atpa[i]) > 4 then
begin
l := Length(tpa);
SetLength(tpa, l + 1);
tpa[l] := MiddleTPA(atpa[i]);
end;

if not (Length(tpa) = 3) then
Exit;

SetLength(VectorArray, 3);

for i := 0 to 2 do
VectorArray[i] := CreateVector(Point(543, 24), tpa[i], True);

angles := [AngleBetween(VectorArray[0], VectorArray[1]),
AngleBetween(VectorArray[1], VectorArray[2]),
AngleBetween(VectorArray[2], VectorArray[0])];

for i := 0 to 2 do
begin
if angles[i] > pi then
angles[i] := math_2pi - angles[i];
{ compare angle between, > 100 then it's the south dot }
if angles[i] > radians(100) then
begin
case i of
0: RefPoint := tpa[2];
1: RefPoint := tpa[0];
2: RefPoint := tpa[1];
end;
{ break the loop, we have reference pt. }
break;
end;
end;


{ Using the south dot to measure compass angle.. }
Result := ArcTan2(-(RefPoint.Y - 24), RefPoint.X - 543) - Radians(80);
Result := fixRad(Result - Pi - 0.05*Pi);
end;

function rs_GetCompassAngleDegrees: Extended;
begin
Result := Degrees(rs_GetCompassAngleRadians());
end;

Ok, this works and I have made Nava2's suggested changes.

Wyn

2011-11-23 22:28:56

From: ReadySteadyGo
(* start math.simba additions *)
type
TVector = record
a: Extended;
b: Extended;
Magnitude: Extended;
end;


function fixRad(rad: Extended): Extended; // by Nava2
var
math_2pi: Extended;
begin
math_2pi := 2*pi;
result := rad;

while (result >= math_2pi) do
result := result - math_2pi;

while (result < 0) do
result := result + math_2pi;
end;

function AngleBetween(v1, v2: TVector): Extended;
var
a1, a2: Extended;
begin
a1 := ArcTan2(v1.b, v1.a);
a2 := ArcTan2(v2.b, v2.a);

Result := fixRad(a1 - a2)
end;


procedure Normalise(var vect: TVector);
begin
vect.a := vect.a / vect.Magnitude;
vect.b := vect.b / vect.Magnitude;
vect.Magnitude := 1;
end;

function CreateVector(Origin, vPoint: TPoint; NormaliseV: Boolean): TVector;
begin
Result.a := vPoint.x - Origin.x;
Result.b := 0 - (vPoint.y - Origin.y); // inverts y axis as well
Result.Magnitude := Sqrt(Sqr(Result.a) + Sqr(Result.b));
if NormaliseV then
Normalise(Result);
end;

(* end math.simba additions *)

function rs_GetCompassAngleRadians: Extended;
var
tpa: TPointArray;
atpa: T2DPointArray;
i, h, l: Integer;
VectorArray: Array of TVector;
RefPoint: TPoint;
angles: TExtendedArray;
math_2pi: Extended;
begin
math_2pi := 2*pi;

{ Colour of 3 E/S/W dots }
FindColorsTolerance(tpa, 2239277, 529, 9, 558, 39, 0);

atpa := SplitTPA(tpa, 1);
SetLength(TPA, 0);

h := High(atpa);
for i := 0 to h do
{ Gets rid of dots under length of 3 and get the MiddleTPA }
if high(atpa[i]) > 4 then
begin
l := Length(tpa);
SetLength(tpa, l + 1);
tpa[l] := MiddleTPA(atpa[i]);
end;

if not (Length(tpa) = 3) then
Exit;

SetLength(VectorArray, 3);

for i := 0 to 2 do
VectorArray[i] := CreateVector(Point(543, 24), tpa[i], True);

angles := [AngleBetween(VectorArray[0], VectorArray[1]),
AngleBetween(VectorArray[1], VectorArray[2]),
AngleBetween(VectorArray[2], VectorArray[0])];

for i := 0 to 2 do
begin
if angles[i] > pi then
angles[i] := math_2pi - angles[i];
{ compare angle between, > 100 then it's the south dot }
if angles[i] > radians(100) then
begin
case i of
0: RefPoint := tpa[2];
1: RefPoint := tpa[0];
2: RefPoint := tpa[1];
end;
{ break the loop, we have reference pt. }
break;
end;
end;


{ Using the south dot to measure compass angle.. }
Result := ArcTan2(-(RefPoint.Y - 24), RefPoint.X - 543) - Radians(80);
Result := fixRad(Result - Pi - 0.05*Pi);
end;

function rs_GetCompassAngleDegrees: Extended;
begin
Result := Degrees(rs_GetCompassAngleRadians());
end;

Ok, this works and I have made Nava2's suggested changes.


Tested and Vouch. Works alot better.

Nava2

2011-11-24 00:33:49


h := High(atpa);
setLength(tpa, h+1);
l := 0;
for i := 0 to h do
{ Gets rid of dots under length of 3 and get the MiddleTPA }
if high(atpa[i]) > 4 then
begin
tpa[l] := MiddleTPA(atpa[i]);
inc(l);
end;

setLength(tpa, l);

Must faster than the other.. :)

ReadySteadyGo

2011-11-24 00:45:45

Updated OP

ReadySteadyGo

2011-11-25 19:22:23

bump

kingarabian

2011-11-25 19:46:46

Has this been pushed?

Coh3n

2011-11-26 02:32:38

Just did it, sorry it took so long.

euphemism

2011-11-26 05:16:29

Much more accurate, indeed; unfortunately, I get an out of range error at this line about every 10 tries with a random direction:


VectorArray[i] := CreateVector(Point(543, 24), tpa[i], True);

ReadySteadyGo

2011-11-26 08:29:27

That's a big problem, I'll look into an alternative.

YoHoJo

2011-11-26 09:04:41

http://villavu.com/forum/showthread.php?t=68274

Nava2

2011-11-26 10:45:24

So, it looks like the issue is that its picking up too many pts.

ReadySteadyGo, you need to find another way to filter the pts, pehaps a larger number, or a max range?

Or perhaps debug /where/ its finding the pts and see if you can figure out where those pts are so you can filer them. Maybe using FilterTPADist or something similar.

ReadySteadyGo

2011-11-26 11:59:21

Please can someone who has got this error please go on the irc, I just can't replicate the error.

Coh3n

2011-11-26 14:39:44

I've committed the length check to avoid out of range errors. The constant spinning… Does that still happen?

i luffs yeww

2011-11-26 15:28:01

From: Coh3n
I've committed the length check to avoid out of range errors. The constant spinning… Does that still happen?


I haven't read through ready's procedure yet, but the issue occurred because it tries to see what the angle is as it's changing angles, which is really an error-prone way to go about it, in my opinion. I think it'd be better to calculate how long it should rotate, rotate for that amount of time, and then either assume it's at the right angle or return the angle, or something of the sort.

ReadySteadyGo

2011-11-26 15:40:43

Yes I was thinking that luffs. I just don't know if the timing would be the same for everyone because of lag etc.

i luffs yeww

2011-11-26 16:57:50

Well if you send events to the client while you're lagging, they tend to be caught anyway (more often if you send them when you're about to 'unlag' or whatever), so it shouldn't matter. But really scripts should account for that, anyway, imo. Or you could in the include, but the way I imagine it being done would take away the chance to have different functionality from the scripter, which I don't like.

Coh3n

2011-11-28 16:16:48

From: i luffs yeww
I haven't read through ready's procedure yet, but the issue occurred because it tries to see what the angle is as it's changing angles, which is really an error-prone way to go about it, in my opinion. I think it'd be better to calculate how long it should rotate, rotate for that amount of time, and then either assume it's at the right angle or return the angle, or something of the sort.
I think his methods just get the compass angle. The part you're talking about would be in MakeCompass, wouldn't it? And nothing has been changed in that procedure.

YoHoJo

2011-12-04 04:17:16

The line 144 error is still happening a lot so something still needs to be tweaked!
(Line 144 out of Range in Overwrite.scar)

Coh3n

2011-12-05 16:23:41

From: YoHoJo
The line 144 error is still happening a lot so something still needs to be tweaked!
(Line 144 out of Range in Overwrite.scar)
Has been fixed in the latest revisions of SRL4 and 5.