dead_reckoning.f90
PROGRAM extract_compass_log
IMPLICIT NONE
CHARACTER(31) :: dt_hr_env ! No. of hours, from environment
CHARACTER(255) :: pos_fpath ! File path to a position file with lat/long
INTEGER:: code ! iostat code
INTEGER:: timevalues(8) ! time values
INTEGER, PARAMETER :: real64=SELECTED_REAL_KIND(15, 307)
LOGICAL::l_verbose=.false. ! Verbosity setting in namelist
REAL(KIND=real64) :: ang_distance ! Angular distance travelled across Earth
REAL(KIND=real64) :: dt_hr ! No. of hours elapsed, from dt_hr_env
REAL(KIND=real64) :: heading ! Compass heading in radians
REAL(KIND=real64) :: lat ! Initial latitude
REAL(KIND=real64) :: long ! Initial longitude
REAL(KIND=real64) :: new_lat ! Final latitude
REAL(KIND=real64) :: new_long ! Final longitude
REAL(KIND=real64) :: speed_kn=5.0 ! Speed in knots
REAL(KIND=real64), PARAMETER :: pi=3.141592654 ! pi
REAL(KIND=real64), PARAMETER :: radius_earth_nm=3443.89 ! Earth radius (nm)
NAMELIST /report_nl/ l_verbose
! Get position file location via $POS_FPATH
CALL get_environment_variable("POS_FPATH",value=pos_fpath,status=code)
IF (code /= 0) THEN
WRITE(0,*) "$POS_FPATH: not set."
STOP 1
END IF
! Read in starting latitude and longitude
OPEN(1,file=pos_fpath,action="read",iostat=code)
IF (code /= 0) THEN
WRITE(0,*) pos_fpath,": position file read failed."
STOP 1
END IF
READ(1,*) lat,long
CLOSE(1)
! Convert to radians, where they belong
lat = (pi/180.0) * lat
long = (pi/180.0) * long
! Read in our report_nl namelist
OPEN(1,file="report.nl",action='read',status='old',iostat=code)
IF (code == 0) THEN
READ(1,nml=report_nl)
CLOSE(1)
END IF
! Read in our duration input
CALL get_environment_variable("TIME_INTERVAL_HRS",value=dt_hr_env,status=code)
IF (code /= 0) THEN
WRITE(0,*) "$TIME_INTERVAL_HRS: not set"
STOP 1
END IF
READ(dt_hr_env,*) dt_hr
! Pretend to extract an average heading from the ship's compass
CALL date_and_time(VALUES=timevalues)
heading = mod(1000 * timevalues(7) + timevalues(8), 60) * 2 * pi / 60
! This is how far we went, in radians:
! (1 knot = 1 nautical mile / 1 hour)
ang_distance = (speed_kn*dt_hr) / radius_earth_nm
! Get the new latitude and longitude
new_lat = ASIN(SIN(lat) * COS(ang_distance) + &
COS(lat) * SIN(ang_distance) * COS(heading))
new_long = long + &
ATAN2(SIN(heading) * SIN(ang_distance) * COS(lat), &
COS(ang_distance) - SIN(lat) * SIN(new_lat))
new_lat = (180.0/pi) * new_lat
new_long = (180.0/pi) * new_long
! Write to standard out, if high verbosity is switched on
IF (l_verbose) THEN
PRINT*, "New position, me hearties:",new_lat," ",new_long
END IF
! Overwrite position file with new lat and long
OPEN(1,file=pos_fpath,action='write')
WRITE(1,*) new_lat,new_long
CLOSE(1)
END PROGRAM