@@ -41,27 +41,29 @@ def global_to_boat_coordinate(boat_heading: float, global_wind_direction: float)
4141
4242
4343def get_true_wind (
44- aw_direction : float ,
45- aw_speed : float ,
46- boat_heading : float ,
47- boat_speed : float ,
44+ aw_dir_deg : float ,
45+ aw_speed_kmph : float ,
46+ boat_heading_deg : float ,
47+ boat_speed_kmph : float ,
48+ ret_rad : bool = True ,
4849) -> tuple [float , float ]:
4950 """Compute the true wind vector from apparent wind and boat motion.
5051
5152 Args:
52- aw_direction (float): Apparent wind direction in degrees (-180, 180]. This is the wind
53+ aw_dir_deg (float): Apparent wind direction in degrees (-180, 180]. This is the wind
5354 as measured relative to the boat (sensor reading).
54- aw_speed (float): Apparent wind speed (same units as boat_speed), e.g., km/h.
55- boat_heading (float): Boat heading in degrees (-180, 180].
56- boat_speed (float): Boat speed over ground (same units as aw_speed), e.g., km/h.
55+ aw_speed_kmph (float): Apparent wind speed in km/h.
56+ boat_heading_deg (float): Boat heading in degrees (-180, 180].
57+ boat_speed_kmph (float): Boat speed over ground in km/h.
58+ ret_rad (bool): If True, return wind direction in radians. If False, return in degrees.
5759 NOTE: All the angles are with respect to global true bearing. It is the
5860 responsibility of the caller to ensure this. Particularly, the apparent wind read by the
5961 sensor is in boat coordinates
6062
6163 Returns:
62- tuple[float, float]: (tw_angle, tw_magnitude )
63- - tw_angle : true wind direction in radians within (-pi, pi].
64- - tw_magnitude : true wind speed
64+ tuple[float, float]: (tw_dir_rad, tw_speed_kmph )
65+ - tw_dir_rad : true wind direction in radians within (-pi, pi].
66+ - tw_speed_kmph : true wind speed in km/h
6567 If the resulting vector magnitude is effectively zero (<= FLOATING_POINT_ERROR_THRESHOLD),
6668 returns (0.0, 0.0). NOTE: The caller is responsible for handling this case, otherwise the
6769 calculations will break down.
@@ -70,65 +72,79 @@ def get_true_wind(
7072 The function computes vector components in an east/north frame, subtracting the boat
7173 motion from the apparent wind to obtain the true wind.
7274 """
73- wind_radians = math .radians (aw_direction )
75+ aw_dir_rad = math .radians (aw_dir_deg )
7476
7577 # boat wind is in the direction of the boat heading (reverse of boat heading)
76- boat_wind_radians = math .radians (cs .bound_to_180 (boat_heading + 180 ))
77- apparent_wind_east = aw_speed * math .sin (wind_radians )
78- apparent_wind_north = aw_speed * math .cos (wind_radians )
78+ bw_dir_rad = math .radians (cs .bound_to_180 (boat_heading_deg + 180 ))
79+ aw_east_kmph = aw_speed_kmph * math .sin (aw_dir_rad )
80+ aw_north_kmph = aw_speed_kmph * math .cos (aw_dir_rad )
7981
80- boat_wind_east = boat_speed * math .sin (boat_wind_radians )
81- boat_wind_north = boat_speed * math .cos (boat_wind_radians )
82+ bw_east_kmph = boat_speed_kmph * math .sin (bw_dir_rad )
83+ bw_north_kmph = boat_speed_kmph * math .cos (bw_dir_rad )
8284
83- true_east = apparent_wind_east - boat_wind_east
84- true_north = apparent_wind_north - boat_wind_north
85+ tw_east_kmph = aw_east_kmph - bw_east_kmph
86+ tw_north_kmph = aw_north_kmph - bw_north_kmph
8587
86- magnitude = math .hypot (true_east , true_north )
87- angle = math .atan2 (true_east , true_north )
88+ tw_speed_kmph = math .hypot (tw_east_kmph , tw_north_kmph )
89+ tw_dir_rad = math .atan2 (tw_east_kmph , tw_north_kmph )
8890
89- if magnitude > FLOATING_POINT_ERROR_THRESHOLD :
90- return angle , magnitude
91+ if ret_rad :
92+ tw_dir = tw_dir_rad
93+ else :
94+ tw_dir = math .degrees (tw_dir_rad )
95+
96+ if tw_speed_kmph > FLOATING_POINT_ERROR_THRESHOLD :
97+ return tw_dir , tw_speed_kmph
9198 return ZERO_VECTOR_CONSTANT , 0.0
9299
93100
94- def get_apparent_wind (tw_direction , tw_speed , boat_heading , boat_speed ) -> tuple [float , float ]:
101+ def get_apparent_wind (
102+ tw_dir_deg : float ,
103+ tw_speed_kmph : float ,
104+ boat_heading_deg : float ,
105+ boat_speed_kmph : float ,
106+ ret_rad : bool = True ,
107+ ) -> tuple [float , float ]:
95108 """Compute the apparent wind vector from true wind and boat motion.
96109
97110 Args:
98- tw_direction (float): True wind direction in radians (measured as atan2(east, north) style)
99- or degrees if caller uses degrees consistently. (This routine converts using math.radians # noqa
100- in the original code; keep inputs consistent with usage.)
101- tw_speed (float): True wind speed (same units as boat_speed), e.g., km/h.
102- boat_heading (float): Boat heading in degrees (-180, 180].
103- boat_speed (float): Boat speed over ground (same units as tw_speed), e.g., km/h.
111+ tw_dir_deg (float): True wind direction in degrees (-180, 180].
112+ tw_speed_kmph (float): True wind speed in km/h.
113+ boat_heading_deg (float): Boat heading in degrees (-180, 180].
114+ boat_speed_kmph (float): Boat speed over ground in km/h.
115+ ret_rad (bool): If True, return wind direction in radians. If False, return in degrees.
104116 NOTE: All the angles are with respect to global true bearing. It is the
105117 responsibility of the caller to ensure this.
106118
107119 Returns:
108- tuple[float, float]: (aw_angle, aw_magnitude )
109- - aw_angle : apparent wind direction in radians within (-pi, pi]
110- - aw_magnitude : apparent wind speed (same units as inputs) .
120+ tuple[float, float]: (aw_dir_rad, aw_speed_kmph )
121+ - aw_dir_rad : apparent wind direction in radians within (-pi, pi]
122+ - aw_speed_kmph : apparent wind speed in km/h .
111123 If the resulting vector magnitude is effectively zero (<= FLOATING_POINT_ERROR_THRESHOLD),
112124 returns (0.0, 0.0). NOTE: The caller is responsible for handling this case, otherwise the
113125 calculations will break down.
114126 """
115- tw_direction = math .radians (tw_direction )
127+ tw_dir_rad = math .radians (tw_dir_deg )
128+
129+ bw_speed_kmph = boat_speed_kmph
130+ bw_dir_rad = math .radians (cs .bound_to_180 (boat_heading_deg + 180.0 ))
131+ bw_east_kmph = bw_speed_kmph * math .sin (bw_dir_rad )
132+ bw_north_kmph = bw_speed_kmph * math .cos (bw_dir_rad )
116133
117- bw_speed = boat_speed
118- bw_direction = math .radians (cs .bound_to_180 (boat_heading + 180.0 ))
119- # print(math.degrees(bw_direction))
120- boat_wind_east = bw_speed * math .sin (bw_direction )
121- boat_wind_north = bw_speed * math .cos (bw_direction )
134+ tw_east_kmph = tw_speed_kmph * math .sin (tw_dir_rad )
135+ tw_north_kmph = tw_speed_kmph * math .cos (tw_dir_rad )
122136
123- tw_speed_east = tw_speed * math . sin ( tw_direction )
124- tw_speed_north = tw_speed * math . cos ( tw_direction )
137+ aw_east_kmph = tw_east_kmph + bw_east_kmph
138+ aw_north_kmph = tw_north_kmph + bw_north_kmph
125139
126- aw_speed_east = tw_speed_east + boat_wind_east
127- aw_speed_north = tw_speed_north + boat_wind_north
140+ aw_speed_kmph = math . hypot ( aw_east_kmph , aw_north_kmph )
141+ aw_dir_rad = math . atan2 ( aw_east_kmph , aw_north_kmph )
128142
129- magnitude = math .hypot (aw_speed_east , aw_speed_north )
130- angle = math .atan2 (aw_speed_east , aw_speed_north )
143+ if ret_rad :
144+ aw_dir = aw_dir_rad
145+ else :
146+ aw_dir = math .degrees (aw_dir_rad )
131147
132- if magnitude > FLOATING_POINT_ERROR_THRESHOLD :
133- return angle , magnitude
148+ if aw_speed_kmph > FLOATING_POINT_ERROR_THRESHOLD :
149+ return aw_dir , aw_speed_kmph
134150 return ZERO_VECTOR_CONSTANT , 0.0
0 commit comments