openrvdas.logger.utils.truewinds.truew

Calculate true winds from vessel speed, course and relative wind

These routines will compute meteorological true winds (direction from which wind is blowing, relative to true north; and speed relative to the fixed earth).

8/08/2017 : Converted from Matlab to python by David Pablo Cohn (david.cohn@gmail.com) using SMOP 0.1; verified on python 2.7-3.5

9/30/2014 : If the true wind has speed and its coming from the north then its direction should be 360deg. The problem was fixed in which the programss output showed 0deg instead of 360deg.

Created: 12/17/96 Developed by: Shawn R. Smith and Mark A. Bourassa Programmed by: Mylene Remigio

Direct questions about algorithm to: wocemet@coaps.fsu.edu

  1#!/usr/bin/env python
  2
  3"""
  4Calculate true winds from vessel speed, course and relative wind
  5
  6These routines will compute meteorological true winds (direction from
  7which wind is blowing, relative to true north; and speed relative to
  8the fixed earth).
  9
 108/08/2017 : Converted from Matlab to python by David Pablo Cohn
 11            (david.cohn@gmail.com) using SMOP 0.1; verified on
 12            python 2.7-3.5
 13
 149/30/2014 : If the true wind has speed and its coming from the north
 15            then its direction should be 360deg. The problem was fixed
 16            in which the programss output showed 0deg instead of 360deg.
 17
 18Created: 12/17/96
 19Developed by: Shawn R. Smith and Mark A. Bourassa
 20Programmed by: Mylene Remigio
 21
 22Direct questions about algorithm to:  wocemet@coaps.fsu.edu
 23"""
 24
 25import logging
 26
 27from math import pi, cos, sin, atan2, sqrt
 28
 29DEFAULT_ZRL = 0.0  # clockwise angle between bow and anemometer reference line
 30DEFAULT_MISSING_VALUES = [-1111.0,  # missing val for course_over_ground
 31                          -9999.0,  # missing val for speed_over_ground
 32                          1111.0,  # missing val for wind_dir
 33                          9999.0,  # missing val for wind_speed
 34                          5555.0,  # missing val for heading
 35                          ]
 36
 37
 38################################################################################
 39def truew(crse=None,
 40          cspd=None,
 41          hd=None,
 42          wdir=None,
 43          wspd=None,
 44          zlr=DEFAULT_ZRL,
 45          wmis=DEFAULT_MISSING_VALUES,
 46          ):
 47    """
 48    FUNCTION truew() - calculates true winds from vessel speed, course and
 49    relative wind
 50
 51    INPUTS
 52
 53    crse      real    Course TOWARD WHICH the vessel is moving over
 54                          the ground. Referenced to true north and the
 55                          fixed earth.
 56    cspd      real    Speed of vessel over the ground. Referenced
 57                          to the fixed earth.
 58    hd        real    Heading toward which bow of vessel is pointing.
 59                          Referenced to true north.
 60    zlr       real    Zero line reference -- angle between bow and
 61                          zero line on anemometer.  Direction is clockwise
 62                          from the bow.  (Use bow=0 degrees as default
 63                          when reference not known.)
 64    wdir      real    Wind direction measured by anemometer,
 65                          referenced to the ship.
 66    wspd      real    Wind speed measured by anemometer,referenced to
 67                          the vessel's frame of reference.
 68    wmis      real    Five element array containing missing values for
 69                          crse, cspd, wdir, wspd, and hd. In the output,
 70                          the missing value for tdir is identical to the
 71                          missing value specified in wmis for wdir.
 72                          Similarly, tspd uses the missing value assigned
 73                          to wmis for wspd.
 74
 75    *** WDIR MUST BE METEOROLOGICAL (DIRECTION FROM)! CRSE AND CSPD MUST
 76        BE RELATIVE TO A FIXED EARTH! ***
 77
 78    OUTPUT VALUES:
 79
 80    tdir      real    True wind direction - referenced to true north
 81                          and the fixed earth with a direction from which
 82                          the wind is blowing (meteorological).
 83    tspd      real    True wind speed - referenced to the fixed earth.
 84    adir      real    Apparent wind direction (direction measured by
 85                          wind vane, relative to true north). IS
 86                          REFERENCED TO TRUE NORTH & IS DIRECTION FROM
 87                          WHICH THE WIND IS BLOWING. Apparent wind
 88                          direction is the sum of the ship relative wind
 89                          direction (measured by wind vane relative to the
 90                          bow), the ship's heading, and the zero-line
 91                          reference angle.  NOTE:  The apparent wind speed
 92                          has a magnitude equal to the wind speed measured
 93                          by the anemometer.
 94
 95    """
 96    # INITIALIZE VARIABLES
 97    adir = 0
 98    dtor = pi / 180
 99
100    # Check course, ship speed, heading, wind direction, and
101    # wind speed for valid values (i.e. neither missing nor
102    # outside physically acceptable ranges).
103    err_mesg = []
104    if crse is None or crse < 0 or crse > 360 or crse == wmis[0]:
105        err_mesg.append('Bad or missing course: %g' % crse)
106    if cspd is None or cspd < 0 or cspd == wmis[1]:
107        err_mesg.append('Bad or missing cspd: %g' % cspd)
108    if wdir is None or wdir < 0 or wdir > 360 or wdir == wmis[2]:
109        err_mesg.append('Bad or missing wind dir: %g' % wdir)
110    if wspd is None or wspd < 0 or wspd == wmis[3]:
111        err_mesg.append('Bad or missing wind speed: %g' % wspd)
112    if hd is None or hd < 0 or hd > 360 or hd == wmis[4]:
113        err_mesg.append('Bad or missing heading: %g' % hd)
114    if zlr < 0.0 or zlr > 360.0:
115        err_mesg.append('Bad or missing zero line reference: %g' % zlr)
116        zlr = 0.0
117
118    if err_mesg:
119        logging.warning('TrueWinds: %s', '; '.join(err_mesg))
120        return (None, None, None)
121
122    # Convert from navigational coordinates to
123    # angles commonly used in mathematics
124    mcrse = 90 - crse
125    # Keep the value between 0 and 360 degrees
126    if (mcrse <= 0.0):
127        mcrse = mcrse + 360.0
128    # Calculate apparent wind direction
129    adir = hd + wdir + zlr
130    # Keep adir between 0 and 360 degrees
131    while adir >= 360.0:
132        adir = adir - 360.0
133
134    # Convert from meteorological coordinates to angles
135    # commonly used in mathematics
136    mwdir = 270.0 - adir
137    # Keep mdir between 0 and 360 degrees
138    if (mwdir <= 0.0):
139        mwdir = mwdir + 360.0
140    if (mwdir > 360.0):
141        mwdir = mwdir - 360.0
142    # Determine the east-west vector component and the
143    # north-south vector component of the true wind
144    x = wspd * cos(mwdir * dtor) + cspd * cos(mcrse * dtor)
145    y = wspd * sin(mwdir * dtor) + cspd * sin(mcrse * dtor)
146    # Use the two vector components to calculate the true wind
147    # speed
148    tspd = sqrt(x * x + y * y)
149    calm_flag = 1
150    # Determine the angle for the true wind
151    if (abs(x) > 1e-05):
152        mtdir = (atan2(y, x)) / dtor
153    else:
154        if (abs(y) > 1e-05):
155            mtdir = 180.0 - (90.0 * y) / abs(y)
156        else:
157            # The true wind speed is essentially zero: winds
158            # are calm and direction is not well defined
159            mtdir = 270.0
160            calm_flag = 0
161    # Convert from the common mathematical angle coordinate to
162    # the meteorological wind direction
163    tdir = 270.0 - mtdir
164    # Make sure that the true wind angle is between
165    # 0 and 360 degrees
166    while tdir < 0.0:
167        tdir = (tdir + 360.0) * calm_flag
168
169    while tdir > 360.0:
170        tdir = (tdir - 360.0) * calm_flag
171
172    # Ensure wmo convention for tdir = 360 for win
173    # from north and tspd > 0
174    if (calm_flag == 1 and (tdir < 0.0001)):
175        tdir = 360.0
176
177    return (tdir, tspd, adir)
178
179
180################################################################################
181if __name__ == '__main__':
182    pass
DEFAULT_ZRL = 0.0
DEFAULT_MISSING_VALUES = [-1111.0, -9999.0, 1111.0, 9999.0, 5555.0]
def truew( crse=None, cspd=None, hd=None, wdir=None, wspd=None, zlr=0.0, wmis=[-1111.0, -9999.0, 1111.0, 9999.0, 5555.0]):
 40def truew(crse=None,
 41          cspd=None,
 42          hd=None,
 43          wdir=None,
 44          wspd=None,
 45          zlr=DEFAULT_ZRL,
 46          wmis=DEFAULT_MISSING_VALUES,
 47          ):
 48    """
 49    FUNCTION truew() - calculates true winds from vessel speed, course and
 50    relative wind
 51
 52    INPUTS
 53
 54    crse      real    Course TOWARD WHICH the vessel is moving over
 55                          the ground. Referenced to true north and the
 56                          fixed earth.
 57    cspd      real    Speed of vessel over the ground. Referenced
 58                          to the fixed earth.
 59    hd        real    Heading toward which bow of vessel is pointing.
 60                          Referenced to true north.
 61    zlr       real    Zero line reference -- angle between bow and
 62                          zero line on anemometer.  Direction is clockwise
 63                          from the bow.  (Use bow=0 degrees as default
 64                          when reference not known.)
 65    wdir      real    Wind direction measured by anemometer,
 66                          referenced to the ship.
 67    wspd      real    Wind speed measured by anemometer,referenced to
 68                          the vessel's frame of reference.
 69    wmis      real    Five element array containing missing values for
 70                          crse, cspd, wdir, wspd, and hd. In the output,
 71                          the missing value for tdir is identical to the
 72                          missing value specified in wmis for wdir.
 73                          Similarly, tspd uses the missing value assigned
 74                          to wmis for wspd.
 75
 76    *** WDIR MUST BE METEOROLOGICAL (DIRECTION FROM)! CRSE AND CSPD MUST
 77        BE RELATIVE TO A FIXED EARTH! ***
 78
 79    OUTPUT VALUES:
 80
 81    tdir      real    True wind direction - referenced to true north
 82                          and the fixed earth with a direction from which
 83                          the wind is blowing (meteorological).
 84    tspd      real    True wind speed - referenced to the fixed earth.
 85    adir      real    Apparent wind direction (direction measured by
 86                          wind vane, relative to true north). IS
 87                          REFERENCED TO TRUE NORTH & IS DIRECTION FROM
 88                          WHICH THE WIND IS BLOWING. Apparent wind
 89                          direction is the sum of the ship relative wind
 90                          direction (measured by wind vane relative to the
 91                          bow), the ship's heading, and the zero-line
 92                          reference angle.  NOTE:  The apparent wind speed
 93                          has a magnitude equal to the wind speed measured
 94                          by the anemometer.
 95
 96    """
 97    # INITIALIZE VARIABLES
 98    adir = 0
 99    dtor = pi / 180
100
101    # Check course, ship speed, heading, wind direction, and
102    # wind speed for valid values (i.e. neither missing nor
103    # outside physically acceptable ranges).
104    err_mesg = []
105    if crse is None or crse < 0 or crse > 360 or crse == wmis[0]:
106        err_mesg.append('Bad or missing course: %g' % crse)
107    if cspd is None or cspd < 0 or cspd == wmis[1]:
108        err_mesg.append('Bad or missing cspd: %g' % cspd)
109    if wdir is None or wdir < 0 or wdir > 360 or wdir == wmis[2]:
110        err_mesg.append('Bad or missing wind dir: %g' % wdir)
111    if wspd is None or wspd < 0 or wspd == wmis[3]:
112        err_mesg.append('Bad or missing wind speed: %g' % wspd)
113    if hd is None or hd < 0 or hd > 360 or hd == wmis[4]:
114        err_mesg.append('Bad or missing heading: %g' % hd)
115    if zlr < 0.0 or zlr > 360.0:
116        err_mesg.append('Bad or missing zero line reference: %g' % zlr)
117        zlr = 0.0
118
119    if err_mesg:
120        logging.warning('TrueWinds: %s', '; '.join(err_mesg))
121        return (None, None, None)
122
123    # Convert from navigational coordinates to
124    # angles commonly used in mathematics
125    mcrse = 90 - crse
126    # Keep the value between 0 and 360 degrees
127    if (mcrse <= 0.0):
128        mcrse = mcrse + 360.0
129    # Calculate apparent wind direction
130    adir = hd + wdir + zlr
131    # Keep adir between 0 and 360 degrees
132    while adir >= 360.0:
133        adir = adir - 360.0
134
135    # Convert from meteorological coordinates to angles
136    # commonly used in mathematics
137    mwdir = 270.0 - adir
138    # Keep mdir between 0 and 360 degrees
139    if (mwdir <= 0.0):
140        mwdir = mwdir + 360.0
141    if (mwdir > 360.0):
142        mwdir = mwdir - 360.0
143    # Determine the east-west vector component and the
144    # north-south vector component of the true wind
145    x = wspd * cos(mwdir * dtor) + cspd * cos(mcrse * dtor)
146    y = wspd * sin(mwdir * dtor) + cspd * sin(mcrse * dtor)
147    # Use the two vector components to calculate the true wind
148    # speed
149    tspd = sqrt(x * x + y * y)
150    calm_flag = 1
151    # Determine the angle for the true wind
152    if (abs(x) > 1e-05):
153        mtdir = (atan2(y, x)) / dtor
154    else:
155        if (abs(y) > 1e-05):
156            mtdir = 180.0 - (90.0 * y) / abs(y)
157        else:
158            # The true wind speed is essentially zero: winds
159            # are calm and direction is not well defined
160            mtdir = 270.0
161            calm_flag = 0
162    # Convert from the common mathematical angle coordinate to
163    # the meteorological wind direction
164    tdir = 270.0 - mtdir
165    # Make sure that the true wind angle is between
166    # 0 and 360 degrees
167    while tdir < 0.0:
168        tdir = (tdir + 360.0) * calm_flag
169
170    while tdir > 360.0:
171        tdir = (tdir - 360.0) * calm_flag
172
173    # Ensure wmo convention for tdir = 360 for win
174    # from north and tspd > 0
175    if (calm_flag == 1 and (tdir < 0.0001)):
176        tdir = 360.0
177
178    return (tdir, tspd, adir)

FUNCTION truew() - calculates true winds from vessel speed, course and relative wind

INPUTS

crse real Course TOWARD WHICH the vessel is moving over the ground. Referenced to true north and the fixed earth. cspd real Speed of vessel over the ground. Referenced to the fixed earth. hd real Heading toward which bow of vessel is pointing. Referenced to true north. zlr real Zero line reference -- angle between bow and zero line on anemometer. Direction is clockwise from the bow. (Use bow=0 degrees as default when reference not known.) wdir real Wind direction measured by anemometer, referenced to the ship. wspd real Wind speed measured by anemometer,referenced to the vessel's frame of reference. wmis real Five element array containing missing values for crse, cspd, wdir, wspd, and hd. In the output, the missing value for tdir is identical to the missing value specified in wmis for wdir. Similarly, tspd uses the missing value assigned to wmis for wspd.

*** WDIR MUST BE METEOROLOGICAL (DIRECTION FROM)! CRSE AND CSPD MUST BE RELATIVE TO A FIXED EARTH! ***

OUTPUT VALUES:

tdir real True wind direction - referenced to true north and the fixed earth with a direction from which the wind is blowing (meteorological). tspd real True wind speed - referenced to the fixed earth. adir real Apparent wind direction (direction measured by wind vane, relative to true north). IS REFERENCED TO TRUE NORTH & IS DIRECTION FROM WHICH THE WIND IS BLOWING. Apparent wind direction is the sum of the ship relative wind direction (measured by wind vane relative to the bow), the ship's heading, and the zero-line reference angle. NOTE: The apparent wind speed has a magnitude equal to the wind speed measured by the anemometer.