Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AC_WPNav/AC_WPNav_OA.cpp
Views: 1798
#include "AC_WPNav_config.h"12#if AC_WPNAV_OA_ENABLED34#include <AP_Math/control.h>5#include <AP_InternalError/AP_InternalError.h>6#include "AC_WPNav_OA.h"78AC_WPNav_OA::AC_WPNav_OA(const AP_InertialNav& inav, const AP_AHRS_View& ahrs, AC_PosControl& pos_control, const AC_AttitudeControl& attitude_control) :9AC_WPNav(inav, ahrs, pos_control, attitude_control)10{11}1213// returns object avoidance adjusted wp location using location class14// returns false if unable to convert from target vector to global coordinates15bool AC_WPNav_OA::get_oa_wp_destination(Location& destination) const16{17// if oa inactive return unadjusted location18if (_oa_state == AP_OAPathPlanner::OA_NOT_REQUIRED) {19return get_wp_destination_loc(destination);20}2122// return latest destination provided by oa path planner23destination = _oa_destination;24return true;25}2627/// set_wp_destination waypoint using position vector (distance from ekf origin in cm)28/// terrain_alt should be true if destination.z is a desired altitude above terrain29/// returns false on failure (likely caused by missing terrain data)30bool AC_WPNav_OA::set_wp_destination(const Vector3f& destination, bool terrain_alt)31{32const bool ret = AC_WPNav::set_wp_destination(destination, terrain_alt);3334if (ret) {35// reset object avoidance state36_oa_state = AP_OAPathPlanner::OA_NOT_REQUIRED;37}3839return ret;40}4142/// get_wp_distance_to_destination - get horizontal distance to destination in cm43/// always returns distance to final destination (i.e. does not use oa adjusted destination)44float AC_WPNav_OA::get_wp_distance_to_destination() const45{46if (_oa_state == AP_OAPathPlanner::OA_NOT_REQUIRED) {47return AC_WPNav::get_wp_distance_to_destination();48}4950return get_horizontal_distance_cm(_inav.get_position_xy_cm(), _destination_oabak.xy());51}5253/// get_wp_bearing_to_destination - get bearing to next waypoint in centi-degrees54/// always returns bearing to final destination (i.e. does not use oa adjusted destination)55int32_t AC_WPNav_OA::get_wp_bearing_to_destination() const56{57if (_oa_state == AP_OAPathPlanner::OA_NOT_REQUIRED) {58return AC_WPNav::get_wp_bearing_to_destination();59}6061return get_bearing_cd(_inav.get_position_xy_cm(), _destination_oabak.xy());62}6364/// true when we have come within RADIUS cm of the waypoint65bool AC_WPNav_OA::reached_wp_destination() const66{67return (_oa_state == AP_OAPathPlanner::OA_NOT_REQUIRED) && AC_WPNav::reached_wp_destination();68}6970/// update_wpnav - run the wp controller - should be called at 100hz or higher71bool AC_WPNav_OA::update_wpnav()72{73// run path planning around obstacles74AP_OAPathPlanner *oa_ptr = AP_OAPathPlanner::get_singleton();75Location current_loc;76if ((oa_ptr != nullptr) && AP::ahrs().get_location(current_loc)) {7778// backup _origin and _destination when not doing oa79if (_oa_state == AP_OAPathPlanner::OA_NOT_REQUIRED) {80_origin_oabak = _origin;81_destination_oabak = _destination;82_terrain_alt_oabak = _terrain_alt;83_next_destination_oabak = _next_destination;84}8586// convert origin, destination and next_destination to Locations and pass into oa87const Location origin_loc(_origin_oabak, _terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);88const Location destination_loc(_destination_oabak, _terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);89const Location next_destination_loc(_next_destination_oabak, _terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);90Location oa_origin_new, oa_destination_new, oa_next_destination_new;91bool dest_to_next_dest_clear = true;92AP_OAPathPlanner::OAPathPlannerUsed path_planner_used = AP_OAPathPlanner::OAPathPlannerUsed::None;93const AP_OAPathPlanner::OA_RetState oa_retstate = oa_ptr->mission_avoidance(current_loc,94origin_loc,95destination_loc,96next_destination_loc,97oa_origin_new,98oa_destination_new,99oa_next_destination_new,100dest_to_next_dest_clear,101path_planner_used);102103switch (oa_retstate) {104105case AP_OAPathPlanner::OA_NOT_REQUIRED:106if (_oa_state != oa_retstate) {107// object avoidance has become inactive so reset target to original destination108if (!set_wp_destination(_destination_oabak, _terrain_alt_oabak)) {109// trigger terrain failsafe110return false;111}112113// if path from destination to next_destination is clear114if (dest_to_next_dest_clear && (oa_ptr->get_options() & AP_OAPathPlanner::OA_OPTION_FAST_WAYPOINTS)) {115// set next destination if non-zero116if (!_next_destination_oabak.is_zero()) {117set_wp_destination_next(_next_destination_oabak);118}119}120_oa_state = oa_retstate;121}122123// ensure we stop at next waypoint124// Note that this check is run on every iteration even if the path planner is not active125if (!dest_to_next_dest_clear) {126force_stop_at_next_wp();127}128break;129130case AP_OAPathPlanner::OA_PROCESSING:131if (oa_ptr->get_options() & AP_OAPathPlanner::OA_OPTION_FAST_WAYPOINTS) {132// if fast waypoint option is set, proceed during processing133break;134}135FALLTHROUGH;136137case AP_OAPathPlanner::OA_ERROR:138// during processing or in case of error stop the vehicle139// by setting the oa_destination to a stopping point140if ((_oa_state != AP_OAPathPlanner::OA_PROCESSING) && (_oa_state != AP_OAPathPlanner::OA_ERROR)) {141// calculate stopping point142Vector3f stopping_point;143get_wp_stopping_point(stopping_point);144_oa_destination = Location(stopping_point, Location::AltFrame::ABOVE_ORIGIN);145_oa_next_destination.zero();146if (set_wp_destination(stopping_point, false)) {147_oa_state = oa_retstate;148}149}150break;151152case AP_OAPathPlanner::OA_SUCCESS:153154// handling of returned destination depends upon path planner used155switch (path_planner_used) {156157case AP_OAPathPlanner::OAPathPlannerUsed::None:158// this should never happen. this means the path planner has returned success but has failed to set the path planner used159INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);160return false;161162case AP_OAPathPlanner::OAPathPlannerUsed::Dijkstras:163// Dijkstra's. Action is only needed if path planner has just became active or the target destination's lat or lon has changed164if ((_oa_state != AP_OAPathPlanner::OA_SUCCESS) || !oa_destination_new.same_latlon_as(_oa_destination)) {165Location origin_oabak_loc(_origin_oabak, _terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);166Location destination_oabak_loc(_destination_oabak, _terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);167oa_destination_new.linearly_interpolate_alt(origin_oabak_loc, destination_oabak_loc);168169// set new OA adjusted destination170if (!set_wp_destination_loc(oa_destination_new)) {171// trigger terrain failsafe172return false;173}174// if new target set successfully, update oa state and destination175_oa_state = oa_retstate;176_oa_destination = oa_destination_new;177178// if a next destination was provided then use it179if ((oa_ptr->get_options() & AP_OAPathPlanner::OA_OPTION_FAST_WAYPOINTS) && !oa_next_destination_new.is_zero()) {180// calculate oa_next_destination_new's altitude using linear interpolation between original origin and destination181// this "next destination" is still an intermediate point between the origin and destination182Location next_destination_oabak_loc(_next_destination_oabak, _terrain_alt_oabak ? Location::AltFrame::ABOVE_TERRAIN : Location::AltFrame::ABOVE_ORIGIN);183oa_next_destination_new.linearly_interpolate_alt(origin_oabak_loc, destination_oabak_loc);184if (set_wp_destination_next_loc(oa_next_destination_new)) {185_oa_next_destination = oa_next_destination_new;186}187}188}189break;190191case AP_OAPathPlanner::OAPathPlannerUsed::BendyRulerHorizontal: {192_oa_state = oa_retstate;193_oa_destination = oa_destination_new;194195// altitude target interpolated from current_loc's distance along the original path196Location target_alt_loc = current_loc;197target_alt_loc.linearly_interpolate_alt(origin_loc, destination_loc);198199// correct target_alt_loc's alt-above-ekf-origin if using terrain altitudes200// positive terr_offset means terrain below vehicle is above ekf origin's altitude201float terr_offset = 0;202if (_terrain_alt_oabak && !get_terrain_offset(terr_offset)) {203// trigger terrain failsafe204return false;205}206207// calculate final destination as an offset from EKF origin in NEU208Vector2f dest_NE;209if (!_oa_destination.get_vector_xy_from_origin_NE(dest_NE)) {210// this should never happen because we can only get here if we have an EKF origin211INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);212return false;213}214Vector3p dest_NEU{dest_NE.x, dest_NE.y, (float)target_alt_loc.alt};215216// pass the desired position directly to the position controller217_pos_control.input_pos_xyz(dest_NEU, terr_offset, 1000.0);218219// update horizontal position controller (vertical is updated in vehicle code)220_pos_control.update_xy_controller();221222// return success without calling parent AC_WPNav223return true;224}225226case AP_OAPathPlanner::OAPathPlannerUsed::BendyRulerVertical: {227_oa_state = oa_retstate;228_oa_destination = oa_destination_new;229230// calculate final destination as an offset from EKF origin in NEU231Vector3f dest_NEU;232if (!_oa_destination.get_vector_from_origin_NEU(dest_NEU)) {233// this should never happen because we can only get here if we have an EKF origin234INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);235return false;236}237238// pass the desired position directly to the position controller as an offset from EKF origin in NEU239Vector3p dest_NEU_p{dest_NEU.x, dest_NEU.y, dest_NEU.z};240_pos_control.input_pos_xyz(dest_NEU_p, 0, 1000.0);241242// update horizontal position controller (vertical is updated in vehicle code)243_pos_control.update_xy_controller();244245// return success without calling parent AC_WPNav246return true;247}248249}250}251}252253// run the non-OA update254return AC_WPNav::update_wpnav();255}256257#endif // Ac_WPNAV_OA_ENABLED258259260