mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-22 00:23:33 +08:00
* FeasibilityChecker: only warn when first waypoint is too far, but still accept mission as valid * feasiblityChecker: make distance to first waypoint check against home position instead of current position, so it is more constant during a flight * Apply suggestions from code review Co-authored-by: Silvan Fuhrer <silvan@auterion.com> * feasibilityCheckerTest: update tests to not fail for first waypoint check * feasibilityChecker: make comment for 1stwaypointcheck event * Feasibility check unit test: fix comment Signed-off-by: Silvan Fuhrer <silvan@auterion.com> --------- Signed-off-by: Silvan Fuhrer <silvan@auterion.com> Co-authored-by: Silvan Fuhrer <silvan@auterion.com>
155 lines
5.8 KiB
C++
155 lines
5.8 KiB
C++
/****************************************************************************
|
|
*
|
|
* Copyright (c) 2013-2019 PX4 Development Team. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Neither the name PX4 nor the names of its contributors may be
|
|
* used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
****************************************************************************/
|
|
/**
|
|
* @file mission_feasibility_checker.cpp
|
|
* Provides checks if mission is feasible given the navigation capabilities
|
|
*
|
|
* @author Lorenz Meier <lm@inf.ethz.ch>
|
|
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
|
* @author Sander Smeets <sander@droneslab.com>
|
|
* @author Nuno Marques <nuno.marques@dronesolutions.io>
|
|
*/
|
|
|
|
#include "mission_feasibility_checker.h"
|
|
|
|
#include "mission_block.h"
|
|
#include "navigator.h"
|
|
|
|
#include <drivers/drv_pwm_output.h>
|
|
#include <lib/geo/geo.h>
|
|
#include <lib/mathlib/mathlib.h>
|
|
#include <systemlib/mavlink_log.h>
|
|
#include <uORB/Subscription.hpp>
|
|
#include <px4_platform_common/events.h>
|
|
|
|
bool
|
|
MissionFeasibilityChecker::checkMissionFeasible(const mission_s &mission)
|
|
{
|
|
// Reset warning flag
|
|
_navigator->get_mission_result()->warning = false;
|
|
|
|
// first check if we have a valid position
|
|
const bool home_valid = _navigator->home_global_position_valid();
|
|
const bool home_alt_valid = _navigator->home_alt_valid();
|
|
|
|
// trivial case: A mission with length zero cannot be valid
|
|
if ((int)mission.count <= 0) {
|
|
return false;
|
|
}
|
|
|
|
if (!home_alt_valid) {
|
|
mavlink_log_info(_navigator->get_mavlink_log_pub(), "Not yet ready for mission, no position lock.\t");
|
|
events::send(events::ID("navigator_mis_no_pos_lock"), events::Log::Info, "Not yet ready for mission, no position lock");
|
|
return false;
|
|
}
|
|
|
|
bool failed = false;
|
|
|
|
for (size_t i = 0; i < mission.count; i++) {
|
|
struct mission_item_s missionitem = {};
|
|
|
|
bool success = _dataman_client.readSync((dm_item_t)mission.mission_dataman_id, i,
|
|
reinterpret_cast<uint8_t *>(&missionitem),
|
|
sizeof(mission_item_s));
|
|
|
|
if (!success) {
|
|
_navigator->get_mission_result()->warning = true;
|
|
/* not supposed to happen unless the datamanager can't access the SD card, etc. */
|
|
return false;
|
|
}
|
|
|
|
if (!_feasibility_checker.processNextItem(missionitem, i, mission.count)) {
|
|
failed = true;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
failed |= _feasibility_checker.someCheckFailed();
|
|
|
|
failed |= !checkMissionAgainstGeofence(mission, _navigator->get_home_position()->alt, home_valid);
|
|
|
|
_navigator->get_mission_result()->warning = failed;
|
|
|
|
return !failed;
|
|
}
|
|
|
|
bool
|
|
MissionFeasibilityChecker::checkMissionAgainstGeofence(const mission_s &mission, float home_alt, bool home_valid)
|
|
{
|
|
if (_navigator->get_geofence().isHomeRequired() && !home_valid) {
|
|
mavlink_log_critical(_navigator->get_mavlink_log_pub(), "Geofence requires valid home position\t");
|
|
events::send(events::ID("navigator_mis_geofence_no_home"), {events::Log::Error, events::LogInternal::Info},
|
|
"Geofence requires a valid home position");
|
|
return false;
|
|
}
|
|
|
|
/* Check if all mission items are inside the geofence (if we have a valid geofence) */
|
|
if (_navigator->get_geofence().valid()) {
|
|
for (size_t i = 0; i < mission.count; i++) {
|
|
struct mission_item_s missionitem = {};
|
|
|
|
bool success = _dataman_client.readSync((dm_item_t)mission.mission_dataman_id, i,
|
|
reinterpret_cast<uint8_t *>(&missionitem),
|
|
sizeof(mission_item_s));
|
|
|
|
if (!success) {
|
|
/* not supposed to happen unless the datamanager can't access the SD card, etc. */
|
|
return false;
|
|
}
|
|
|
|
if (missionitem.altitude_is_relative && !home_valid) {
|
|
mavlink_log_critical(_navigator->get_mavlink_log_pub(), "Geofence requires valid home position\t");
|
|
events::send(events::ID("navigator_mis_geofence_no_home2"), {events::Log::Error, events::LogInternal::Info},
|
|
"Geofence requires a valid home position");
|
|
return false;
|
|
}
|
|
|
|
// Geofence function checks against home altitude amsl
|
|
missionitem.altitude = missionitem.altitude_is_relative ? missionitem.altitude + home_alt : missionitem.altitude;
|
|
|
|
if (MissionBlock::item_contains_position(missionitem) && !_navigator->get_geofence().checkPointAgainstAllGeofences(
|
|
missionitem.lat, missionitem.lon, missionitem.altitude)) {
|
|
|
|
mavlink_log_critical(_navigator->get_mavlink_log_pub(), "Geofence violation for waypoint %zu\t", i + 1);
|
|
events::send<int16_t>(events::ID("navigator_mis_geofence_violation"), {events::Log::Error, events::LogInternal::Info},
|
|
"Geofence violation for waypoint {1}",
|
|
i + 1);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|