@@ -116,7 +116,7 @@ def __init__(self, projection: pyproj.Geod, expedition: Expedition) -> None:
116116 self ._next_ship_underwater_st_time = self ._time
117117
118118 def simulate (self ) -> ScheduleOk | ScheduleProblem :
119- # TODO: instrument config mapping (as introduced in #269) should be helpful for refactoring here...
119+ # TODO: instrument config mapping (as introduced in #269) should be helpful for refactoring here (i.e. #236) ...
120120
121121 for wp_i , waypoint in enumerate (self ._expedition .schedule .waypoints ):
122122 # sail towards waypoint
@@ -140,6 +140,7 @@ def simulate(self) -> ScheduleOk | ScheduleProblem:
140140
141141 # wait while measurements are being done
142142 self ._progress_time_stationary (time_passed )
143+
143144 return ScheduleOk (self ._time , self ._measurements_to_simulate )
144145
145146 def _progress_time_traveling_towards (self , location : Location ) -> None :
@@ -150,90 +151,101 @@ def _progress_time_traveling_towards(self, location: Location) -> None:
150151 self ._projection ,
151152 )
152153 end_time = self ._time + time_to_reach
154+ distance_to_move = ship_speed_meter_per_second * time_to_reach .total_seconds ()
155+
153156 # note all ADCP measurements
154157 if self ._expedition .instruments_config .adcp_config is not None :
155- location = self ._location
156- time = self ._time
157- while self ._next_adcp_time <= end_time :
158- time_to_sail = self ._next_adcp_time - time
159- distance_to_move = (
160- ship_speed_meter_per_second * time_to_sail .total_seconds ()
161- )
162- geodfwd : tuple [float , float , float ] = self ._projection .fwd (
163- lons = location .lon ,
164- lats = location .lat ,
165- az = azimuth1 ,
166- dist = distance_to_move ,
167- )
168- location = Location (latitude = geodfwd [1 ], longitude = geodfwd [0 ])
169- time = time + time_to_sail
170-
158+ adcp_times , adcp_lons , adcp_lats = self ._get_underway_measurements (
159+ self ._expedition .instruments_config .adcp_config ,
160+ azimuth1 ,
161+ distance_to_move ,
162+ time_to_reach ,
163+ )
164+
165+ for time , lon , lat in zip (adcp_times , adcp_lons , adcp_lats , strict = False ):
166+ location = Location (latitude = lat , longitude = lon )
171167 self ._measurements_to_simulate .adcps .append (
172168 Spacetime (location = location , time = time )
173169 )
174170
175- self ._next_adcp_time = (
176- self ._next_adcp_time
177- + self ._expedition .instruments_config .adcp_config .period
178- )
179-
180171 # note all ship underwater ST measurements
181172 if self ._expedition .instruments_config .ship_underwater_st_config is not None :
182- location = self ._location
183- time = self ._time
184- while self ._next_ship_underwater_st_time <= end_time :
185- time_to_sail = self ._next_ship_underwater_st_time - time
186- distance_to_move = (
187- ship_speed_meter_per_second * time_to_sail .total_seconds ()
188- )
189- geodfwd : tuple [float , float , float ] = self ._projection .fwd (
190- lons = location .lon ,
191- lats = location .lat ,
192- az = azimuth1 ,
193- dist = distance_to_move ,
194- )
195- location = Location (latitude = geodfwd [1 ], longitude = geodfwd [0 ])
196- time = time + time_to_sail
197-
198- self ._measurements_to_simulate .ship_underwater_sts .append (
173+ st_times , st_lons , st_lats = self ._get_underway_measurements (
174+ self ._expedition .instruments_config .ship_underwater_st_config ,
175+ azimuth1 ,
176+ distance_to_move ,
177+ time_to_reach ,
178+ )
179+
180+ for time , lon , lat in zip (st_times , st_lons , st_lats , strict = False ):
181+ location = Location (latitude = lat , longitude = lon )
182+ self ._measurements_to_simulate .adcps .append (
199183 Spacetime (location = location , time = time )
200184 )
201185
202- self ._next_ship_underwater_st_time = (
203- self ._next_ship_underwater_st_time
204- + self ._expedition .instruments_config .ship_underwater_st_config .period
205- )
206-
207186 self ._time = end_time
208187 self ._location = location
209188
189+ def _get_underway_measurements (
190+ self ,
191+ underway_instrument_config ,
192+ azimuth ,
193+ distance_to_move ,
194+ time_to_reach : timedelta ,
195+ ):
196+ """Get the times and locations of measurements between a waypoint (or the start) and the next waypoint, for underway instruments."""
197+ period = underway_instrument_config .period
198+ npts = (time_to_reach .total_seconds () / period .total_seconds ()) + 1
199+ times = [self ._time + i * period for i in range (1 , int (npts ) + 1 )]
200+
201+ geodfwd = self ._projection .fwd_intermediate (
202+ lon1 = self ._location .lon ,
203+ lat1 = self ._location .lat ,
204+ azi1 = azimuth ,
205+ npts = npts ,
206+ del_s = distance_to_move / npts ,
207+ return_back_azimuth = False ,
208+ )
209+
210+ return times , geodfwd .lons , geodfwd .lats
211+
210212 def _progress_time_stationary (self , time_passed : timedelta ) -> None :
211213 end_time = self ._time + time_passed
212214
213- # note all ADCP measurements
215+ # note all ADCP measurements (stationary at wp)
214216 if self ._expedition .instruments_config .adcp_config is not None :
215- while self ._next_adcp_time <= end_time :
217+ adcp_times = self ._get_underway_stationary_times (
218+ self ._expedition .instruments_config .adcp_config , time_passed
219+ )
220+
221+ for time in adcp_times :
216222 self ._measurements_to_simulate .adcps .append (
217- Spacetime (self ._location , self ._next_adcp_time )
218- )
219- self ._next_adcp_time = (
220- self ._next_adcp_time
221- + self ._expedition .instruments_config .adcp_config .period
223+ Spacetime (location = self ._location , time = time )
222224 )
223225
224- # note all ship underwater ST measurements
226+ # note all underwater ST measurements (stationary at wp)
225227 if self ._expedition .instruments_config .ship_underwater_st_config is not None :
226- while self ._next_ship_underwater_st_time <= end_time :
228+ st_times = self ._get_underway_stationary_times (
229+ self ._expedition .instruments_config .ship_underwater_st_config ,
230+ time_passed ,
231+ )
232+ for time in st_times :
227233 self ._measurements_to_simulate .ship_underwater_sts .append (
228- Spacetime (self ._location , self ._next_ship_underwater_st_time )
229- )
230- self ._next_ship_underwater_st_time = (
231- self ._next_ship_underwater_st_time
232- + self ._expedition .instruments_config .ship_underwater_st_config .period
234+ Spacetime (location = self ._location , time = time )
233235 )
234236
235237 self ._time = end_time
236238
239+ def _get_underway_stationary_times (self , underway_instrument_config , time_passed ):
240+ npts = (
241+ time_passed .total_seconds ()
242+ / underway_instrument_config .period .total_seconds ()
243+ ) + 1
244+ return [
245+ self ._time + i * underway_instrument_config .period
246+ for i in range (1 , int (npts ) + 1 )
247+ ]
248+
237249 def _make_measurements (self , waypoint : Waypoint ) -> timedelta :
238250 # if there are no instruments, there is no time cost
239251 if waypoint .instrument is None :
0 commit comments