@@ -15,12 +15,12 @@ AC_WPNav_OA::AC_WPNav_OA(const AP_AHRS_View& ahrs, AC_PosControl& pos_control, c
1515// Falls back to original destination if OA is not active.
1616bool AC_WPNav_OA::get_oa_wp_destination (Location& destination) const
1717{
18- // if oa inactive return unadjusted location
18+ // Return unmodified global destination if OA is not active
1919 if (_oa_state == AP_OAPathPlanner::OA_NOT_REQUIRED) {
2020 return get_wp_destination_loc (destination);
2121 }
2222
23- // return latest destination provided by oa path planner
23+ // OA is active — return path- planner-adjusted intermediate destination
2424 destination = _oa_destination;
2525 return true ;
2626}
@@ -29,6 +29,7 @@ bool AC_WPNav_OA::get_oa_wp_destination(Location& destination) const
2929// See set_wp_destination_NEU_m() for full details.
3030bool AC_WPNav_OA::set_wp_destination_NEU_cm (const Vector3f& destination_neu_cm, bool is_terrain_alt)
3131{
32+ // Convert input from centimeters to meters and delegate to meter version
3233 return set_wp_destination_NEU_m (destination_neu_cm * 0.01 , is_terrain_alt);
3334}
3435
@@ -38,8 +39,10 @@ bool AC_WPNav_OA::set_wp_destination_NEU_cm(const Vector3f& destination_neu_cm,
3839// - Resets OA state on success.
3940bool AC_WPNav_OA::set_wp_destination_NEU_m (const Vector3f& destination_neu_m, bool is_terrain_alt)
4041{
42+ // Call base implementation to set destination and terrain-altitude flag
4143 const bool ret = AC_WPNav::set_wp_destination_NEU_m (destination_neu_m, is_terrain_alt);
4244
45+ // If destination set successfully, reset OA state to inactive
4346 if (ret) {
4447 // reset object avoidance state
4548 _oa_state = AP_OAPathPlanner::OA_NOT_REQUIRED;
@@ -52,69 +55,78 @@ bool AC_WPNav_OA::set_wp_destination_NEU_m(const Vector3f& destination_neu_m, bo
5255// See get_wp_distance_to_destination_m() for full details.
5356float AC_WPNav_OA::get_wp_distance_to_destination_cm () const
5457{
58+ // Convert horizontal distance from meters to centimeters
5559 return get_wp_distance_to_destination_m () * 100.0 ;
5660}
5761
5862// Returns the horizontal distance to the final destination in meters.
5963// Ignores OA-adjusted targets and always measures to the original final destination.
6064float AC_WPNav_OA::get_wp_distance_to_destination_m () const
6165{
66+ // Return horizontal distance to final destination (ignoring OA intermediate goals)
6267 if (_oa_state == AP_OAPathPlanner::OA_NOT_REQUIRED) {
6368 return AC_WPNav::get_wp_distance_to_destination_m ();
6469 }
6570
71+ // Compute distance to original destination using backed-up NEU position
6672 return get_horizontal_distance (_pos_control.get_pos_estimate_NEU_m ().xy ().tofloat (), _destination_oabak_neu_m.xy ());
6773}
6874
6975// Returns the bearing to the final destination in centidegrees.
7076// See get_wp_bearing_to_destination_rad() for full details.
7177int32_t AC_WPNav_OA::get_wp_bearing_to_destination_cd () const
7278{
79+ // Convert bearing to destination (in radians) to centidegrees
7380 return rad_to_cd (get_wp_bearing_to_destination_rad ());
7481}
7582
7683// Returns the bearing to the final destination in radians.
7784// Ignores OA-adjusted targets and always calculates from original final destination.
7885float AC_WPNav_OA::get_wp_bearing_to_destination_rad () const
7986{
87+ // Use base class method if object avoidance is inactive
8088 if (_oa_state == AP_OAPathPlanner::OA_NOT_REQUIRED) {
8189 return AC_WPNav::get_wp_bearing_to_destination_rad ();
8290 }
8391
92+ // Return bearing to the original destination, not the OA-adjusted one
8493 return get_bearing_rad (_pos_control.get_pos_estimate_NEU_m ().xy ().tofloat (), _destination_oabak_neu_m.xy ());
8594}
8695
8796// Returns true if the vehicle has reached the final destination within radius threshold.
8897// Ignores OA-adjusted intermediate destinations.
8998bool AC_WPNav_OA::reached_wp_destination () const
9099{
100+ // Only consider the waypoint reached if OA is inactive and base class condition is met
91101 return (_oa_state == AP_OAPathPlanner::OA_NOT_REQUIRED) && AC_WPNav::reached_wp_destination ();
92102}
93103
94104// Runs the waypoint navigation update loop, including OA path planning logic.
95105// Delegates to parent class if OA is not active or not required.
96106bool AC_WPNav_OA::update_wpnav ()
97107{
98- // run path planning around obstacles
108+ // Run path planning logic using the active OA planner
99109 AP_OAPathPlanner *oa_ptr = AP_OAPathPlanner::get_singleton ();
100110 Location current_loc;
101111 if ((oa_ptr != nullptr ) && AP::ahrs ().get_location (current_loc)) {
102112
103- // backup _origin and _destination_neu_m when not doing oa
113+ // Backup current path state before OA modifies it
104114 if (_oa_state == AP_OAPathPlanner::OA_NOT_REQUIRED) {
105115 _origin_oabak_neu_m = _origin_neu_m;
106116 _destination_oabak_neu_m = _destination_neu_m;
107117 _is_terrain_alt_oabak = _is_terrain_alt;
108118 _next_destination_oabak_neu_m = _next_destination_neu_m;
109119 }
110120
111- // convert origin, destination and next_destination to Locations and pass into oa
121+ // Convert backup path state to global Location objects for planner input
112122 const Location origin_loc (_origin_oabak_neu_m * 100.0 , _is_terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);
113123 const Location destination_loc (_destination_oabak_neu_m * 100.0 , _is_terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);
114124 const Location next_destination_loc (_next_destination_oabak_neu_m * 100.0 , _is_terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);
115125 Location oa_origin_new, oa_destination_new, oa_next_destination_new;
116126 bool dest_to_next_dest_clear = true ;
117127 AP_OAPathPlanner::OAPathPlannerUsed path_planner_used = AP_OAPathPlanner::OAPathPlannerUsed::None;
128+
129+ // Request obstacle-avoidance-adjusted path from planner
118130 const AP_OAPathPlanner::OA_RetState oa_retstate = oa_ptr->mission_avoidance (current_loc,
119131 origin_loc,
120132 destination_loc,
@@ -128,6 +140,7 @@ bool AC_WPNav_OA::update_wpnav()
128140 switch (oa_retstate) {
129141
130142 case AP_OAPathPlanner::OA_NOT_REQUIRED:
143+ // OA is no longer needed — restore original destination and optionally set next
131144 if (_oa_state != oa_retstate) {
132145 // object avoidance has become inactive so reset target to original destination
133146 if (!set_wp_destination_NEU_m (_destination_oabak_neu_m, _is_terrain_alt_oabak)) {
@@ -145,23 +158,23 @@ bool AC_WPNav_OA::update_wpnav()
145158 _oa_state = oa_retstate;
146159 }
147160
148- // ensure we stop at next waypoint
161+ // Prevent transitioning past this waypoint if path to next is unclear
149162 // Note that this check is run on every iteration even if the path planner is not active
150163 if (!dest_to_next_dest_clear) {
151164 force_stop_at_next_wp ();
152165 }
153166 break ;
154167
155168 case AP_OAPathPlanner::OA_PROCESSING:
169+ // Allow continued movement while OA path is processing if fast-waypointing is enabled
156170 if (oa_ptr->get_options () & AP_OAPathPlanner::OA_OPTION_FAST_WAYPOINTS) {
157171 // if fast waypoint option is set, proceed during processing
158172 break ;
159173 }
160174 FALLTHROUGH;
161175
162176 case AP_OAPathPlanner::OA_ERROR:
163- // during processing or in case of error stop the vehicle
164- // by setting the oa_destination to a stopping point
177+ // OA temporarily failing — stop vehicle at current position
165178 if ((_oa_state != AP_OAPathPlanner::OA_PROCESSING) && (_oa_state != AP_OAPathPlanner::OA_ERROR)) {
166179 // calculate stopping point
167180 Vector3f stopping_point_neu_m;
@@ -176,7 +189,7 @@ bool AC_WPNav_OA::update_wpnav()
176189
177190 case AP_OAPathPlanner::OA_SUCCESS:
178191
179- // handling of returned destination depends upon path planner used
192+ // Handle result differently depending on which OA planner was used
180193 switch (path_planner_used) {
181194
182195 case AP_OAPathPlanner::OAPathPlannerUsed::None:
@@ -186,6 +199,7 @@ bool AC_WPNav_OA::update_wpnav()
186199
187200 case AP_OAPathPlanner::OAPathPlannerUsed::Dijkstras:
188201 // Dijkstra's. Action is only needed if path planner has just became active or the target destination's lat or lon has changed
202+ // Interpolate altitude and set new target if different or first OA success
189203 if ((_oa_state != AP_OAPathPlanner::OA_SUCCESS) || !oa_destination_new.same_latlon_as (_oa_destination)) {
190204 Location origin_oabak_loc (_origin_oabak_neu_m * 100.0 , _is_terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);
191205 Location destination_oabak_loc (_destination_oabak_neu_m * 100 , _is_terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);
@@ -200,7 +214,7 @@ bool AC_WPNav_OA::update_wpnav()
200214 _oa_state = oa_retstate;
201215 _oa_destination = oa_destination_new;
202216
203- // if a next destination was provided then use it
217+ // Set next destination if provided
204218 if ((oa_ptr->get_options () & AP_OAPathPlanner::OA_OPTION_FAST_WAYPOINTS) && !oa_next_destination_new.is_zero ()) {
205219 // calculate oa_next_destination_new's altitude using linear interpolation between original origin and destination
206220 // this "next destination" is still an intermediate point between the origin and destination
@@ -217,19 +231,18 @@ bool AC_WPNav_OA::update_wpnav()
217231 _oa_state = oa_retstate;
218232 _oa_destination = oa_destination_new;
219233
220- // altitude target interpolated from current_loc's distance along the original path
234+ // Adjust altitude based on current progress along the path
221235 Location target_alt_loc = current_loc;
222236 target_alt_loc.linearly_interpolate_alt (origin_loc, destination_loc);
223237
224- // correct target_alt_loc's alt-above-ekf-origin if using terrain altitudes
225- // positive terr_offset_m means terrain below vehicle is above ekf origin's altitude
238+ // Get terrain offset if needed
226239 float terr_offset_m = 0 ;
227240 if (_is_terrain_alt_oabak && !get_terrain_offset_m (terr_offset_m)) {
228241 // trigger terrain failsafe
229242 return false ;
230243 }
231244
232- // calculate final destination as an offset from EKF origin in NEU
245+ // Convert global destination to NEU vector and pass directly to position controller
233246 Vector2f destination_ne_m;
234247 if (!_oa_destination.get_vector_xy_from_origin_NE_m (destination_ne_m)) {
235248 // this should never happen because we can only get here if we have an EKF origin
@@ -254,7 +267,7 @@ bool AC_WPNav_OA::update_wpnav()
254267 _oa_state = oa_retstate;
255268 _oa_destination = oa_destination_new;
256269
257- // calculate final destination as an offset from EKF origin in NEU
270+ // Convert final destination to NEU offset and push to position controller
258271 Vector3f destination_neu_m;
259272 if (!_oa_destination.get_vector_from_origin_NEU_m (destination_neu_m)) {
260273 // this should never happen because we can only get here if we have an EKF origin
@@ -277,7 +290,7 @@ bool AC_WPNav_OA::update_wpnav()
277290 }
278291 }
279292
280- // run the non-OA update
293+ // Run standard waypoint update if OA was not active or handled above
281294 return AC_WPNav::update_wpnav ();
282295}
283296
0 commit comments