mirror of https://github.com/ArduPilot/ardupilot
AP_Mount: add get_poi
Co-authored-by: Randy Mackay <rmackay9@yahoo.com>
This commit is contained in:
parent
11e541f123
commit
eb5ead462b
|
@ -609,6 +609,18 @@ void AP_Mount::send_gimbal_manager_status(mavlink_channel_t chan)
|
||||||
}
|
}
|
||||||
#endif // HAL_GCS_ENABLED
|
#endif // HAL_GCS_ENABLED
|
||||||
|
|
||||||
|
#if AP_MOUNT_POI_TO_LATLONALT_ENABLED
|
||||||
|
// get poi information. Returns true on success and fills in gimbal attitude, location and poi location
|
||||||
|
bool AP_Mount::get_poi(uint8_t instance, Quaternion &quat, Location &loc, Location &poi_loc) const
|
||||||
|
{
|
||||||
|
auto *backend = get_instance(instance);
|
||||||
|
if (backend == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return backend->get_poi(instance, quat, loc, poi_loc);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// get mount's current attitude in euler angles in degrees. yaw angle is in body-frame
|
// get mount's current attitude in euler angles in degrees. yaw angle is in body-frame
|
||||||
// returns true on success
|
// returns true on success
|
||||||
bool AP_Mount::get_attitude_euler(uint8_t instance, float& roll_deg, float& pitch_deg, float& yaw_bf_deg)
|
bool AP_Mount::get_attitude_euler(uint8_t instance, float& roll_deg, float& pitch_deg, float& yaw_bf_deg)
|
||||||
|
|
|
@ -195,6 +195,11 @@ public:
|
||||||
// send a GIMBAL_MANAGER_STATUS message to GCS
|
// send a GIMBAL_MANAGER_STATUS message to GCS
|
||||||
void send_gimbal_manager_status(mavlink_channel_t chan);
|
void send_gimbal_manager_status(mavlink_channel_t chan);
|
||||||
|
|
||||||
|
#if AP_MOUNT_POI_TO_LATLONALT_ENABLED
|
||||||
|
// get poi information. Returns true on success and fills in gimbal attitude, location and poi location
|
||||||
|
bool get_poi(uint8_t instance, Quaternion &quat, Location &loc, Location &poi_loc) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
// get mount's current attitude in euler angles in degrees. yaw angle is in body-frame
|
// get mount's current attitude in euler angles in degrees. yaw angle is in body-frame
|
||||||
// returns true on success
|
// returns true on success
|
||||||
bool get_attitude_euler(uint8_t instance, float& roll_deg, float& pitch_deg, float& yaw_bf_deg);
|
bool get_attitude_euler(uint8_t instance, float& roll_deg, float& pitch_deg, float& yaw_bf_deg);
|
||||||
|
|
|
@ -3,16 +3,29 @@
|
||||||
#include <AP_AHRS/AP_AHRS.h>
|
#include <AP_AHRS/AP_AHRS.h>
|
||||||
#include <GCS_MAVLink/GCS.h>
|
#include <GCS_MAVLink/GCS.h>
|
||||||
#include <AP_Logger/AP_Logger.h>
|
#include <AP_Logger/AP_Logger.h>
|
||||||
|
#include <AP_Terrain/AP_Terrain.h>
|
||||||
|
|
||||||
extern const AP_HAL::HAL& hal;
|
extern const AP_HAL::HAL& hal;
|
||||||
|
|
||||||
#define AP_MOUNT_UPDATE_DT 0.02 // update rate in seconds. update() should be called at this rate
|
#define AP_MOUNT_UPDATE_DT 0.02 // update rate in seconds. update() should be called at this rate
|
||||||
|
#define AP_MOUNT_POI_REQUEST_TIMEOUT_MS 30000 // POI calculations continue to be updated for this many seconds after last request
|
||||||
|
#define AP_MOUNT_POI_RESULT_TIMEOUT_MS 3000 // POI calculations valid for 3 seconds
|
||||||
|
#define AP_MOUNT_POI_DIST_M_MAX 10000 // POI calculations limit of 10,000m (10km)
|
||||||
|
|
||||||
// Default init function for every mount
|
// Default init function for every mount
|
||||||
void AP_Mount_Backend::init()
|
void AP_Mount_Backend::init()
|
||||||
{
|
{
|
||||||
// setting default target sysid from parameters
|
// setting default target sysid from parameters
|
||||||
_target_sysid = _params.sysid_default.get();
|
_target_sysid = _params.sysid_default.get();
|
||||||
|
|
||||||
|
#if AP_MOUNT_POI_TO_LATLONALT_ENABLED
|
||||||
|
// create a calculation thread for poi.
|
||||||
|
if (!hal.scheduler->thread_create(FUNCTOR_BIND_MEMBER(&AP_Mount_Backend::calculate_poi, void),
|
||||||
|
"mount_calc_poi",
|
||||||
|
8192, AP_HAL::Scheduler::PRIORITY_IO, -1)) {
|
||||||
|
GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "Mount: failed to start POI thread");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// set device id of this instance, for MNTx_DEVID parameter
|
// set device id of this instance, for MNTx_DEVID parameter
|
||||||
|
@ -414,6 +427,127 @@ void AP_Mount_Backend::write_log(uint64_t timestamp_us)
|
||||||
AP::logger().WriteCriticalBlock(&pkt, sizeof(pkt));
|
AP::logger().WriteCriticalBlock(&pkt, sizeof(pkt));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if AP_MOUNT_POI_TO_LATLONALT_ENABLED
|
||||||
|
// get poi information. Returns true on success and fills in gimbal attitude, location and poi location
|
||||||
|
bool AP_Mount_Backend::get_poi(uint8_t instance, Quaternion &quat, Location &loc, Location &poi_loc)
|
||||||
|
{
|
||||||
|
WITH_SEMAPHORE(poi_calculation.sem);
|
||||||
|
|
||||||
|
// record time of request
|
||||||
|
const uint32_t now_ms = AP_HAL::millis();
|
||||||
|
poi_calculation.poi_request_ms = now_ms;
|
||||||
|
|
||||||
|
// check if poi calculated recently
|
||||||
|
if (now_ms - poi_calculation.poi_update_ms > AP_MOUNT_POI_RESULT_TIMEOUT_MS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check attitude is valid
|
||||||
|
if (poi_calculation.att_quat.is_nan()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
quat = poi_calculation.att_quat;
|
||||||
|
loc = poi_calculation.loc;
|
||||||
|
poi_loc = poi_calculation.poi_loc;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate the Location that the gimbal is pointing at
|
||||||
|
void AP_Mount_Backend::calculate_poi()
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
// run this loop at 10hz
|
||||||
|
hal.scheduler->delay(100);
|
||||||
|
|
||||||
|
// calculate poi if requested within last 30 seconds
|
||||||
|
{
|
||||||
|
WITH_SEMAPHORE(poi_calculation.sem);
|
||||||
|
if ((poi_calculation.poi_request_ms == 0) ||
|
||||||
|
(AP_HAL::millis() - poi_calculation.poi_request_ms > AP_MOUNT_POI_REQUEST_TIMEOUT_MS)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the current location of vehicle
|
||||||
|
const AP_AHRS &ahrs = AP::ahrs();
|
||||||
|
Location curr_loc;
|
||||||
|
if (!ahrs.get_location(curr_loc)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// change vehicle alt to AMSL
|
||||||
|
curr_loc.change_alt_frame(Location::AltFrame::ABSOLUTE);
|
||||||
|
|
||||||
|
// project forward from vehicle looking for terrain
|
||||||
|
// start testing at vehicle's location
|
||||||
|
Location test_loc = curr_loc;
|
||||||
|
Location prev_test_loc = curr_loc;
|
||||||
|
|
||||||
|
// get terrain altitude (AMSL) at test_loc
|
||||||
|
auto terrain = AP_Terrain::get_singleton();
|
||||||
|
float terrain_amsl_m;
|
||||||
|
if ((terrain == nullptr) || !terrain->height_amsl(test_loc, terrain_amsl_m, true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieve gimbal attitude
|
||||||
|
Quaternion quat;
|
||||||
|
if (!get_attitude_quaternion(quat)) {
|
||||||
|
// gimbal attitude unavailable
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// iteratively move test_loc forward until its alt-above-sea-level is below terrain-alt-above-sea-level
|
||||||
|
const float dist_increment_m = MAX(terrain->get_grid_spacing(), 10);
|
||||||
|
const float mount_pitch_deg = degrees(quat.get_euler_pitch());
|
||||||
|
const float mount_yaw_ef_deg = wrap_180(degrees(quat.get_euler_yaw()) + degrees(ahrs.get_yaw()));
|
||||||
|
float total_dist_m = 0;
|
||||||
|
bool get_terrain_alt_success = true;
|
||||||
|
float prev_terrain_amsl_m = terrain_amsl_m;
|
||||||
|
while (total_dist_m < AP_MOUNT_POI_DIST_M_MAX && (test_loc.alt * 0.01) > terrain_amsl_m) {
|
||||||
|
total_dist_m += dist_increment_m;
|
||||||
|
|
||||||
|
// backup previous test location and terrain amsl
|
||||||
|
prev_test_loc = test_loc;
|
||||||
|
prev_terrain_amsl_m = terrain_amsl_m;
|
||||||
|
|
||||||
|
// move test location forward
|
||||||
|
test_loc.offset_bearing_and_pitch(mount_yaw_ef_deg, mount_pitch_deg, dist_increment_m);
|
||||||
|
|
||||||
|
// get terrain's alt-above-sea-level (at test_loc)
|
||||||
|
// fail if terrain alt cannot be retrieved
|
||||||
|
if (!terrain->height_amsl(test_loc, terrain_amsl_m, true) || std::isnan(terrain_amsl_m)) {
|
||||||
|
get_terrain_alt_success = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if a fail occurred above when getting terrain alt then restart calculations from the beginning
|
||||||
|
if (!get_terrain_alt_success) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (total_dist_m >= AP_MOUNT_POI_DIST_M_MAX) {
|
||||||
|
// unable to find terrain within dist_max
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test location has dropped below terrain
|
||||||
|
// interpolate along line between prev_test_loc and test_loc
|
||||||
|
float dist_interp_m = linear_interpolate(0, dist_increment_m, 0, prev_test_loc.alt * 0.01 - prev_terrain_amsl_m, test_loc.alt * 0.01 - terrain_amsl_m);
|
||||||
|
{
|
||||||
|
WITH_SEMAPHORE(poi_calculation.sem);
|
||||||
|
poi_calculation.poi_loc = prev_test_loc;
|
||||||
|
poi_calculation.poi_loc.offset_bearing_and_pitch(mount_yaw_ef_deg, mount_pitch_deg, dist_interp_m);
|
||||||
|
poi_calculation.att_quat = {quat[0], quat[1], quat[2], quat[3]};
|
||||||
|
poi_calculation.loc = curr_loc;
|
||||||
|
poi_calculation.poi_update_ms = AP_HAL::millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// get pilot input (in the range -1 to +1) received through RC
|
// get pilot input (in the range -1 to +1) received through RC
|
||||||
void AP_Mount_Backend::get_rc_input(float& roll_in, float& pitch_in, float& yaw_in) const
|
void AP_Mount_Backend::get_rc_input(float& roll_in, float& pitch_in, float& yaw_in) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -182,6 +182,11 @@ public:
|
||||||
// send camera settings message to GCS
|
// send camera settings message to GCS
|
||||||
virtual void send_camera_settings(mavlink_channel_t chan) const {}
|
virtual void send_camera_settings(mavlink_channel_t chan) const {}
|
||||||
|
|
||||||
|
#if AP_MOUNT_POI_TO_LATLONALT_ENABLED
|
||||||
|
// get poi information. Returns true on success and fills in gimbal attitude, location and poi location
|
||||||
|
bool get_poi(uint8_t instance, Quaternion &quat, Location &loc, Location &poi_loc);
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// rangefinder
|
// rangefinder
|
||||||
//
|
//
|
||||||
|
@ -221,6 +226,11 @@ protected:
|
||||||
// returns true if mavlink heartbeat should be suppressed for this gimbal (only used by Solo gimbal)
|
// returns true if mavlink heartbeat should be suppressed for this gimbal (only used by Solo gimbal)
|
||||||
virtual bool suppress_heartbeat() const { return false; }
|
virtual bool suppress_heartbeat() const { return false; }
|
||||||
|
|
||||||
|
#if AP_MOUNT_POI_TO_LATLONALT_ENABLED
|
||||||
|
// calculate the Location that the gimbal is pointing at
|
||||||
|
void calculate_poi();
|
||||||
|
#endif
|
||||||
|
|
||||||
// get pilot input (in the range -1 to +1) received through RC
|
// get pilot input (in the range -1 to +1) received through RC
|
||||||
void get_rc_input(float& roll_in, float& pitch_in, float& yaw_in) const;
|
void get_rc_input(float& roll_in, float& pitch_in, float& yaw_in) const;
|
||||||
|
|
||||||
|
@ -269,6 +279,17 @@ protected:
|
||||||
MountTarget rate_rads; // rate target in rad/s
|
MountTarget rate_rads; // rate target in rad/s
|
||||||
} mnt_target;
|
} mnt_target;
|
||||||
|
|
||||||
|
#if AP_MOUNT_POI_TO_LATLONALT_ENABLED
|
||||||
|
struct {
|
||||||
|
HAL_Semaphore sem; // semaphore protecting this structure
|
||||||
|
uint32_t poi_request_ms; // system time POI was last requested
|
||||||
|
uint32_t poi_update_ms; // system time POI was calculated
|
||||||
|
Location loc; // gimbal location used for poi calculation
|
||||||
|
Location poi_loc; // location of the POI
|
||||||
|
Quaternion att_quat; // attitude quaternion of the gimbal
|
||||||
|
} poi_calculation;
|
||||||
|
#endif
|
||||||
|
|
||||||
Location _roi_target; // roi target location
|
Location _roi_target; // roi target location
|
||||||
bool _roi_target_set; // true if the roi target has been set
|
bool _roi_target_set; // true if the roi target has been set
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AP_HAL/AP_HAL_Boards.h>
|
#include <AP_HAL/AP_HAL_Boards.h>
|
||||||
|
#include <AP_Terrain/AP_Terrain.h>
|
||||||
|
|
||||||
#ifndef HAL_MOUNT_ENABLED
|
#ifndef HAL_MOUNT_ENABLED
|
||||||
#define HAL_MOUNT_ENABLED 1
|
#define HAL_MOUNT_ENABLED 1
|
||||||
|
@ -48,3 +49,7 @@
|
||||||
#ifndef HAL_MOUNT_VIEWPRO_ENABLED
|
#ifndef HAL_MOUNT_VIEWPRO_ENABLED
|
||||||
#define HAL_MOUNT_VIEWPRO_ENABLED AP_MOUNT_BACKEND_DEFAULT_ENABLED && BOARD_FLASH_SIZE > 1024
|
#define HAL_MOUNT_VIEWPRO_ENABLED AP_MOUNT_BACKEND_DEFAULT_ENABLED && BOARD_FLASH_SIZE > 1024
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef AP_MOUNT_POI_TO_LATLONALT_ENABLED
|
||||||
|
#define AP_MOUNT_POI_TO_LATLONALT_ENABLED HAL_MOUNT_ENABLED && AP_TERRAIN_AVAILABLE && BOARD_FLASH_SIZE > 1024
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue