PRINT "RINGRIG.BAS 15Feb15 tests direction calculation from AUTOP9TTS in circle 0 to 359"
OPEN "RINGRIG.TXT" FOR OUTPUT AS #1
PRINT "Angle   W4(LatB)  W5(LonB)      W1(Calculated)   Error"
rmserror = 0 'RMS (Root Mean Square) value of error from all 360 tests.

'need to declare as integers, or will default to real floating values ?
'DIM W1, W2, W3, W4, W5, w6, w7, w8, w9, w10, w11, w12, w13, b0, b1, b14, b15, b22, b23 AS LONG 'Picaxe variables
DIM W1 AS LONG: DIM W2 AS LONG: DIM W3 AS LONG: DIM W4 AS LONG: DIM W5 AS LONG: DIM w6 AS LONG
DIM W7 AS LONG: DIM w8 AS LONG: DIM w9 AS LONG: DIM W10 AS LONG: DIM w11 AS LONG: DIM w12 AS LONG
DIM w13 AS LONG: DIM b0 AS LONG: DIM b1 AS LONG: DIM b14 AS LONG: DIM b15 AS LONG: DIM b22 AS LONG
DIM b23 AS LONG: DIM i AS LONG: DIM ii AS LONG



'keep values in rig lower for if 16 bit integers were used

DIM A, LatD, LonD, COSLATREAL AS SINGLE  'real ringrig variables
LatD = 10000: LonD = 10000: R = 5000 'real ringrig variables
COSLATREAL = COS(51 * 3.14159 / 180)

FOR i = 0 TO 359 STEP 1  '0 to 359 degrees from destination out to boat
  ii = i + 180 'ii is direction from boat back to destination = that calculated
  IF ii > 359 THEN
    ii = ii - 360
  END IF
  A = i * 3.14159 / 180 'A in radians
  LatB = LatD + COS(A) * R 'Latitude of Boat
  LonB = LonD - SIN(A) * R / COSLATREAL 'Longitude of Boat (Note degrees WEST are less, and /COS)

  'Feed input into autopilot logic in w4, w5, w8, w9 to get calculated angle in w1.
  b0 = 51: W4 = INT(LatB):  b1 = 0: W5 = INT(LonB) 'Rig calculated Boat GPS Position.
  b14 = 51: w8 = LatD: b15 = 0: w9 = LonD 'Rig fixed destination position.



'Imported code from AUTOP9TTS.BAS 13Feb15

 'calculate approximate target heading based on difference in lat/lons.
 'This based on just minutes if two positions have same lat and lon degrees.
 'If different degrees, then scale minutes and modify based on degrees.
 'Scaling is used to avoid overflow when a long distance appart.
 'This arithmetic overwrites the values of GPS and Destination lat/lons.
 'Temp variables available: w6,w11,w12.

 '1v change minutes if not same values of degrees for GPS and Destination.
 IF b0 <> b14 OR b1 <> b15 THEN 'NOT same value of degrees in lat or lon
  'work with units of 0.1 minutes of lat/lon i.e. 100x less accurate.
  w11 = b0 * 600: w12 = W4 / 100 '1t was *300 and /50 GPS lat/lon
  W4 = w11 + w12 'latitude LSD is 0.1 minutes = 1/600th degree
  w11 = b1 * 600: w12 = W5 / 100
  W5 = w11 + w12 'longitude LSD is 0.1 minutes = 1/600th degree
  w11 = b14 * 600: w12 = w8 / 100 'Destination lat/lon
  w8 = w11 + w12 'latitude LSD is 0.1 minutes = 1/600th degree '26Jan15 Problem?
  w11 = b15 * 600: w12 = w9 / 100
  w9 = w11 + w12 'longitude LSD is 0.1 minutes = 1/600th degree '26Jan15 Problem?
 END IF
 
 '09Feb15 use new COSLAT function near end of program, instead of earlier approximation.
 '13Feb15 call coslat 'get 100 * Cos(Lat) where Lat is average of GPS and Destination latitudes.
 '13Feb15 b1 = b22 / 10 'original code using b1 can now be used....
 'now just the values of minutes (or scaled minutes) can be used ...
   
 IF w8 > W4 THEN 'Dest Lat > GPS Lat
   w12 = w8 - W4 'Diff Lat
   IF w9 < W5 THEN 'Dest Lon east of GPS Lon
     w13 = W5 - w9 'Diff lon
     GOSUB scalew12w13 'scale if either more than 1000 to avoid overflow
   ELSE 'Dest Lon west of GPS Lon
     w13 = w9 - W5 'Diff lon
     GOSUB scalew12w13 'scale if either more than 1000 to avoid overflow
     w6 = 359 ''12Feb15 was 360
     w13 = w6 - w13 'was w13 = 360 - w13
   END IF
 ELSE 'Dest Lat < GPS Lat
   w12 = W4 - w8 'Diff Lat
   IF w9 < W5 THEN 'Dest Lon east of GPS Lon
     w13 = W5 - w9 'Diff lon
     GOSUB scalew12w13 'scale if either more than 1000 to avoid overflow
     w6 = 180
     w13 = w6 - w13 'was w13 = 180 - w13
   ELSE 'Dest Lon west of GPS Lon
     w13 = w9 - W5 'Diff lon
     GOSUB scalew12w13 'scale if either more than 1000 to avoid overflow
     '12Feb15  w6 = 180
     w13 = w13 + 180 'was w13 = w6 + w13 'was w13 + 180
   END IF
 END IF
 
 W1 = w13 'make this the target heading THIS MAKES THE METHOD ACTIVE
 GOTO afterscalesub '1t was x so subroutine near place called from - for clarity

scalew12w13: '13Feb15 scale w12 and w13 to less than 600 so can * by up to 100
 IF w12 < 600 AND w13 < 600 THEN
   GOTO endscale
 END IF
 w12 = w12 / 2: w13 = w13 / 2 'make both smaller
 GOTO scalew12w13 'repeat until both less than 600
endscale:
'13Feb15 if w12 > 1000 or w13 > 1000 then
'13Feb15   w12 = w12 / 100
'13Feb15   w13 = w13 / 100
'13Feb15 endif
 GOSUB coslat 'get 100 * Cos(Lat) where Lat is average of GPS and Destination latitudes.
 w13 = w13 * b22 / 100 '13Feb15 old code was w13 = w13 * b1 / 10 '1v b1 was COSLAT
 IF w13 < w12 THEN
   w13 = w13 * 45 / w12
 ELSE
   w12 = w12 * 45 / w13
   w13 = 90 - w12
 END IF
 RETURN


coslat:   '09Feb15 returns COS(Lat) * 100 in b22. e.g. COS(50)=0.64. b22=64.
   '13Feb15 COS=114-Lat e.g. 64 for Lat 51. Was 115 so less accurate at 51.
   'Average Lat between GPS in b0 and Destination waypoint in b14 is used.
   b22 = b0 + b14: b22 = b22 / 2 'average.
   b23 = 114: b22 = b23 - b22 'approximation in b22 is 115 - Lat in degrees. 13Feb15
   RETURN

 
afterscalesub:
aftercalchdg:  'W1 now holds the Target Heading that the boat must steer towards

'END OF IMPORTED CODE FROM AUTOP9TTS.BAS

  errorv = W1 - ii 'error in degrees between direction and calculated direction
  if errorv >= 180 then 'true error can only be 0 to 180
    errorv = 360 - errorv
  endif
  rmserror = rmserror + ( errorv * errorv )


  PRINT "II="; ii; " W4(LatB)="; W4; " W5(LonB)="; W5; " W1(A)="; W1; "Error="; errorv
  PRINT #1, "II="; ii; " W4(LatB)="; W4; " W5(LonB)="; W5; " W1(A)="; W1; "Error="; errorv

NEXT

rmserror = SQR(rmserror/360)
PRINT "RMS (Root Mean Square) value of all errors = "; rmserror
PRINT #1, "RMS (Root Mean Square) value of all errors = "; rmserror

CLOSE #1

STOP

