mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-23 14:47:44 +08:00
Merge branch 'mpc_rc' of https://github.com/TickTock-/Firmware into rc_merged
This commit is contained in:
@@ -225,7 +225,7 @@ void frsky_send_frame2(int uart)
|
||||
float course = 0, lat = 0, lon = 0, speed = 0, alt = 0;
|
||||
char lat_ns = 0, lon_ew = 0;
|
||||
int sec = 0;
|
||||
if (global_pos.global_valid) {
|
||||
if (global_pos.timestamp != 0 && hrt_absolute_time() < global_pos.timestamp + 20000) {
|
||||
time_t time_gps = global_pos.time_gps_usec / 1000000;
|
||||
struct tm *tm_gps = gmtime(&time_gps);
|
||||
|
||||
|
||||
+73
-125
@@ -1,9 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.ethz.ch>
|
||||
* Lorenz Meier <lm@inf.ethz.ch>
|
||||
* Copyright (C) 2012, 2014 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
|
||||
@@ -42,6 +39,7 @@
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#include <geo/geo.h>
|
||||
@@ -52,124 +50,58 @@
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* Azimuthal Equidistant Projection
|
||||
* formulas according to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html
|
||||
*/
|
||||
|
||||
/* values for map projection */
|
||||
static double phi_1;
|
||||
static double sin_phi_1;
|
||||
static double cos_phi_1;
|
||||
static double lambda_0;
|
||||
static double scale;
|
||||
|
||||
__EXPORT void map_projection_init(double lat_0, double lon_0) //lat_0, lon_0 are expected to be in correct format: -> 47.1234567 and not 471234567
|
||||
__EXPORT void map_projection_init(struct map_projection_reference_s *ref, double lat_0, double lon_0) //lat_0, lon_0 are expected to be in correct format: -> 47.1234567 and not 471234567
|
||||
{
|
||||
/* notation and formulas according to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html */
|
||||
phi_1 = lat_0 / 180.0 * M_PI;
|
||||
lambda_0 = lon_0 / 180.0 * M_PI;
|
||||
|
||||
sin_phi_1 = sin(phi_1);
|
||||
cos_phi_1 = cos(phi_1);
|
||||
|
||||
/* calculate local scale by using the relation of true distance and the distance on plane */ //TODO: this is a quick solution, there are probably easier ways to determine the scale
|
||||
|
||||
/* 1) calculate true distance d on sphere to a point: http://www.movable-type.co.uk/scripts/latlong.html */
|
||||
|
||||
double lat1 = phi_1;
|
||||
double lon1 = lambda_0;
|
||||
|
||||
double lat2 = phi_1 + 0.5 / 180 * M_PI;
|
||||
double lon2 = lambda_0 + 0.5 / 180 * M_PI;
|
||||
double sin_lat_2 = sin(lat2);
|
||||
double cos_lat_2 = cos(lat2);
|
||||
double d = acos(sin(lat1) * sin_lat_2 + cos(lat1) * cos_lat_2 * cos(lon2 - lon1)) * CONSTANTS_RADIUS_OF_EARTH;
|
||||
|
||||
/* 2) calculate distance rho on plane */
|
||||
double k_bar = 0;
|
||||
double c = acos(sin_phi_1 * sin_lat_2 + cos_phi_1 * cos_lat_2 * cos(lon2 - lambda_0));
|
||||
|
||||
if (0 != c)
|
||||
k_bar = c / sin(c);
|
||||
|
||||
double x2 = k_bar * (cos_lat_2 * sin(lon2 - lambda_0)); //Projection of point 2 on plane
|
||||
double y2 = k_bar * ((cos_phi_1 * sin_lat_2 - sin_phi_1 * cos_lat_2 * cos(lon2 - lambda_0)));
|
||||
double rho = sqrt(pow(x2, 2) + pow(y2, 2));
|
||||
|
||||
scale = d / rho;
|
||||
ref->lat = lat_0 / 180.0 * M_PI;
|
||||
ref->lon = lon_0 / 180.0 * M_PI;
|
||||
|
||||
ref->sin_lat = sin(ref->lat);
|
||||
ref->cos_lat = cos(ref->lat);
|
||||
}
|
||||
|
||||
__EXPORT void map_projection_project(double lat, double lon, float *x, float *y)
|
||||
__EXPORT void map_projection_project(struct map_projection_reference_s *ref, double lat, double lon, float *x, float *y)
|
||||
{
|
||||
/* notation and formulas accoring to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html */
|
||||
double phi = lat / 180.0 * M_PI;
|
||||
double lambda = lon / 180.0 * M_PI;
|
||||
double lat_rad = lat / 180.0 * M_PI;
|
||||
double lon_rad = lon / 180.0 * M_PI;
|
||||
|
||||
double sin_phi = sin(phi);
|
||||
double cos_phi = cos(phi);
|
||||
double sin_lat = sin(lat_rad);
|
||||
double cos_lat = cos(lat_rad);
|
||||
double cos_d_lon = cos(lon_rad - ref->lon);
|
||||
|
||||
double k_bar = 0;
|
||||
/* using small angle approximation (formula in comment is without aproximation) */
|
||||
double c = acos(sin_phi_1 * sin_phi + cos_phi_1 * cos_phi * (1 - pow((lambda - lambda_0), 2) / 2)); //double c = acos( sin_phi_1 * sin_phi + cos_phi_1 * cos_phi * cos(lambda - lambda_0) );
|
||||
double c = acos(ref->sin_lat * sin_lat + ref->cos_lat * cos_lat * cos_d_lon);
|
||||
double k = (c == 0.0) ? 1.0 : (c / sin(c));
|
||||
|
||||
if (0 != c)
|
||||
k_bar = c / sin(c);
|
||||
|
||||
/* using small angle approximation (formula in comment is without aproximation) */
|
||||
*y = k_bar * (cos_phi * (lambda - lambda_0)) * scale;//*y = k_bar * (cos_phi * sin(lambda - lambda_0)) * scale;
|
||||
*x = k_bar * ((cos_phi_1 * sin_phi - sin_phi_1 * cos_phi * (1 - pow((lambda - lambda_0), 2) / 2))) * scale; // *x = k_bar * ((cos_phi_1 * sin_phi - sin_phi_1 * cos_phi * cos(lambda - lambda_0))) * scale;
|
||||
|
||||
// printf("%phi_1=%.10f, lambda_0 =%.10f\n", phi_1, lambda_0);
|
||||
*x = k * (ref->cos_lat * sin_lat - ref->sin_lat * cos_lat * cos_d_lon) * CONSTANTS_RADIUS_OF_EARTH;
|
||||
*y = k * cos_lat * sin(lon_rad - ref->lon) * CONSTANTS_RADIUS_OF_EARTH;
|
||||
}
|
||||
|
||||
__EXPORT void map_projection_reproject(float x, float y, double *lat, double *lon)
|
||||
__EXPORT void map_projection_reproject(struct map_projection_reference_s *ref, float x, float y, double *lat, double *lon)
|
||||
{
|
||||
/* notation and formulas accoring to: http://mathworld.wolfram.com/AzimuthalEquidistantProjection.html */
|
||||
|
||||
double x_descaled = x / scale;
|
||||
double y_descaled = y / scale;
|
||||
|
||||
double c = sqrt(pow(x_descaled, 2) + pow(y_descaled, 2));
|
||||
float x_rad = x / CONSTANTS_RADIUS_OF_EARTH;
|
||||
float y_rad = y / CONSTANTS_RADIUS_OF_EARTH;
|
||||
double c = sqrtf(x_rad * x_rad + y_rad * y_rad);
|
||||
double sin_c = sin(c);
|
||||
double cos_c = cos(c);
|
||||
|
||||
double lat_sphere = 0;
|
||||
double lat_rad;
|
||||
double lon_rad;
|
||||
|
||||
if (c != 0)
|
||||
lat_sphere = asin(cos_c * sin_phi_1 + (x_descaled * sin_c * cos_phi_1) / c);
|
||||
else
|
||||
lat_sphere = asin(cos_c * sin_phi_1);
|
||||
|
||||
// printf("lat_sphere = %.10f\n",lat_sphere);
|
||||
|
||||
double lon_sphere = 0;
|
||||
|
||||
if (phi_1 == M_PI / 2) {
|
||||
//using small angle approximation (formula in comment is without aproximation)
|
||||
lon_sphere = (lambda_0 - y_descaled / x_descaled); //lon_sphere = (lambda_0 + atan2(-y_descaled, x_descaled));
|
||||
|
||||
} else if (phi_1 == -M_PI / 2) {
|
||||
//using small angle approximation (formula in comment is without aproximation)
|
||||
lon_sphere = (lambda_0 + y_descaled / x_descaled); //lon_sphere = (lambda_0 + atan2(y_descaled, x_descaled));
|
||||
if (c != 0.0) {
|
||||
lat_rad = asin(cos_c * ref->sin_lat + (x_rad * sin_c * ref->cos_lat) / c);
|
||||
lon_rad = (ref->lon + atan2(y_rad * sin_c, c * ref->cos_lat * cos_c - x_rad * ref->sin_lat * sin_c));
|
||||
|
||||
} else {
|
||||
|
||||
lon_sphere = (lambda_0 + atan2(y_descaled * sin_c , c * cos_phi_1 * cos_c - x_descaled * sin_phi_1 * sin_c));
|
||||
//using small angle approximation
|
||||
// double denominator = (c * cos_phi_1 * cos_c - x_descaled * sin_phi_1 * sin_c);
|
||||
// if(denominator != 0)
|
||||
// {
|
||||
// lon_sphere = (lambda_0 + (y_descaled * sin_c) / denominator);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ...
|
||||
// }
|
||||
lat_rad = ref->lat;
|
||||
lon_rad = ref->lon;
|
||||
}
|
||||
|
||||
// printf("lon_sphere = %.10f\n",lon_sphere);
|
||||
|
||||
*lat = lat_sphere * 180.0 / M_PI;
|
||||
*lon = lon_sphere * 180.0 / M_PI;
|
||||
|
||||
*lat = lat_rad * 180.0 / M_PI;
|
||||
*lon = lon_rad * 180.0 / M_PI;
|
||||
}
|
||||
|
||||
|
||||
@@ -207,7 +139,7 @@ __EXPORT float get_bearing_to_next_waypoint(double lat_now, double lon_now, doub
|
||||
return theta;
|
||||
}
|
||||
|
||||
__EXPORT void get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float* v_n, float* v_e)
|
||||
__EXPORT void get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float *v_n, float *v_e)
|
||||
{
|
||||
double lat_now_rad = lat_now * M_DEG_TO_RAD;
|
||||
double lon_now_rad = lon_now * M_DEG_TO_RAD;
|
||||
@@ -222,7 +154,7 @@ __EXPORT void get_vector_to_next_waypoint(double lat_now, double lon_now, double
|
||||
*v_e = CONSTANTS_RADIUS_OF_EARTH * sin(d_lon) * cos(lat_next_rad);
|
||||
}
|
||||
|
||||
__EXPORT void get_vector_to_next_waypoint_fast(double lat_now, double lon_now, double lat_next, double lon_next, float* v_n, float* v_e)
|
||||
__EXPORT void get_vector_to_next_waypoint_fast(double lat_now, double lon_now, double lat_next, double lon_next, float *v_n, float *v_e)
|
||||
{
|
||||
double lat_now_rad = lat_now * M_DEG_TO_RAD;
|
||||
double lon_now_rad = lon_now * M_DEG_TO_RAD;
|
||||
@@ -248,7 +180,7 @@ __EXPORT void add_vector_to_global_position(double lat_now, double lon_now, floa
|
||||
|
||||
// Additional functions - @author Doug Weibel <douglas.weibel@colorado.edu>
|
||||
|
||||
__EXPORT int get_distance_to_line(struct crosstrack_error_s * crosstrack_error, double lat_now, double lon_now, double lat_start, double lon_start, double lat_end, double lon_end)
|
||||
__EXPORT int get_distance_to_line(struct crosstrack_error_s *crosstrack_error, double lat_now, double lon_now, double lat_start, double lon_start, double lat_end, double lon_end)
|
||||
{
|
||||
// This function returns the distance to the nearest point on the track line. Distance is positive if current
|
||||
// position is right of the track and negative if left of the track as seen from a point on the track line
|
||||
@@ -265,7 +197,7 @@ __EXPORT int get_distance_to_line(struct crosstrack_error_s * crosstrack_error,
|
||||
crosstrack_error->bearing = 0.0f;
|
||||
|
||||
// Return error if arguments are bad
|
||||
if (lat_now == 0.0d || lon_now == 0.0d || lat_start == 0.0d || lon_start == 0.0d || lat_end == 0.0d || lon_end == 0.0d) return return_value;
|
||||
if (lat_now == 0.0d || lon_now == 0.0d || lat_start == 0.0d || lon_start == 0.0d || lat_end == 0.0d || lon_end == 0.0d) { return return_value; }
|
||||
|
||||
bearing_end = get_bearing_to_next_waypoint(lat_now, lon_now, lat_end, lon_end);
|
||||
bearing_track = get_bearing_to_next_waypoint(lat_start, lon_start, lat_end, lon_end);
|
||||
@@ -296,8 +228,8 @@ __EXPORT int get_distance_to_line(struct crosstrack_error_s * crosstrack_error,
|
||||
}
|
||||
|
||||
|
||||
__EXPORT int get_distance_to_arc(struct crosstrack_error_s * crosstrack_error, double lat_now, double lon_now, double lat_center, double lon_center,
|
||||
float radius, float arc_start_bearing, float arc_sweep)
|
||||
__EXPORT int get_distance_to_arc(struct crosstrack_error_s *crosstrack_error, double lat_now, double lon_now, double lat_center, double lon_center,
|
||||
float radius, float arc_start_bearing, float arc_sweep)
|
||||
{
|
||||
// This function returns the distance to the nearest point on the track arc. Distance is positive if current
|
||||
// position is right of the arc and negative if left of the arc as seen from the closest point on the arc and
|
||||
@@ -316,29 +248,29 @@ __EXPORT int get_distance_to_arc(struct crosstrack_error_s * crosstrack_error, d
|
||||
crosstrack_error->bearing = 0.0f;
|
||||
|
||||
// Return error if arguments are bad
|
||||
if (lat_now == 0.0d || lon_now == 0.0d || lat_center == 0.0d || lon_center == 0.0d || radius == 0.0d) return return_value;
|
||||
if (lat_now == 0.0d || lon_now == 0.0d || lat_center == 0.0d || lon_center == 0.0d || radius == 0.0d) { return return_value; }
|
||||
|
||||
|
||||
if (arc_sweep >= 0) {
|
||||
bearing_sector_start = arc_start_bearing;
|
||||
bearing_sector_end = arc_start_bearing + arc_sweep;
|
||||
|
||||
if (bearing_sector_end > 2.0f * M_PI_F) bearing_sector_end -= M_TWOPI_F;
|
||||
if (bearing_sector_end > 2.0f * M_PI_F) { bearing_sector_end -= M_TWOPI_F; }
|
||||
|
||||
} else {
|
||||
bearing_sector_end = arc_start_bearing;
|
||||
bearing_sector_start = arc_start_bearing - arc_sweep;
|
||||
|
||||
if (bearing_sector_start < 0.0f) bearing_sector_start += M_TWOPI_F;
|
||||
if (bearing_sector_start < 0.0f) { bearing_sector_start += M_TWOPI_F; }
|
||||
}
|
||||
|
||||
in_sector = false;
|
||||
|
||||
// Case where sector does not span zero
|
||||
if (bearing_sector_end >= bearing_sector_start && bearing_now >= bearing_sector_start && bearing_now <= bearing_sector_end) in_sector = true;
|
||||
if (bearing_sector_end >= bearing_sector_start && bearing_now >= bearing_sector_start && bearing_now <= bearing_sector_end) { in_sector = true; }
|
||||
|
||||
// Case where sector does span zero
|
||||
if (bearing_sector_end < bearing_sector_start && (bearing_now > bearing_sector_start || bearing_now < bearing_sector_end)) in_sector = true;
|
||||
if (bearing_sector_end < bearing_sector_start && (bearing_now > bearing_sector_start || bearing_now < bearing_sector_end)) { in_sector = true; }
|
||||
|
||||
// If in the sector then calculate distance and bearing to closest point
|
||||
if (in_sector) {
|
||||
@@ -394,8 +326,8 @@ __EXPORT int get_distance_to_arc(struct crosstrack_error_s * crosstrack_error, d
|
||||
}
|
||||
|
||||
__EXPORT float get_distance_to_point_global_wgs84(double lat_now, double lon_now, float alt_now,
|
||||
double lat_next, double lon_next, float alt_next,
|
||||
float *dist_xy, float *dist_z)
|
||||
double lat_next, double lon_next, float alt_next,
|
||||
float *dist_xy, float *dist_z)
|
||||
{
|
||||
double current_x_rad = lat_next / 180.0 * M_PI;
|
||||
double current_y_rad = lon_next / 180.0 * M_PI;
|
||||
@@ -419,8 +351,8 @@ __EXPORT float get_distance_to_point_global_wgs84(double lat_now, double lon_now
|
||||
|
||||
|
||||
__EXPORT float mavlink_wpm_distance_to_point_local(float x_now, float y_now, float z_now,
|
||||
float x_next, float y_next, float z_next,
|
||||
float *dist_xy, float *dist_z)
|
||||
float x_next, float y_next, float z_next,
|
||||
float *dist_xy, float *dist_z)
|
||||
{
|
||||
float dx = x_now - x_next;
|
||||
float dy = y_now - y_next;
|
||||
@@ -442,15 +374,19 @@ __EXPORT float _wrap_pi(float bearing)
|
||||
int c = 0;
|
||||
while (bearing >= M_PI_F) {
|
||||
bearing -= M_TWOPI_F;
|
||||
if (c++ > 3)
|
||||
|
||||
if (c++ > 3) {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
c = 0;
|
||||
while (bearing < -M_PI_F) {
|
||||
bearing += M_TWOPI_F;
|
||||
if (c++ > 3)
|
||||
|
||||
if (c++ > 3) {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
return bearing;
|
||||
@@ -466,15 +402,19 @@ __EXPORT float _wrap_2pi(float bearing)
|
||||
int c = 0;
|
||||
while (bearing >= M_TWOPI_F) {
|
||||
bearing -= M_TWOPI_F;
|
||||
if (c++ > 3)
|
||||
|
||||
if (c++ > 3) {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
c = 0;
|
||||
while (bearing < 0.0f) {
|
||||
bearing += M_TWOPI_F;
|
||||
if (c++ > 3)
|
||||
|
||||
if (c++ > 3) {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
return bearing;
|
||||
@@ -490,15 +430,19 @@ __EXPORT float _wrap_180(float bearing)
|
||||
int c = 0;
|
||||
while (bearing >= 180.0f) {
|
||||
bearing -= 360.0f;
|
||||
if (c++ > 3)
|
||||
|
||||
if (c++ > 3) {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
c = 0;
|
||||
while (bearing < -180.0f) {
|
||||
bearing += 360.0f;
|
||||
if (c++ > 3)
|
||||
|
||||
if (c++ > 3) {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
return bearing;
|
||||
@@ -514,15 +458,19 @@ __EXPORT float _wrap_360(float bearing)
|
||||
int c = 0;
|
||||
while (bearing >= 360.0f) {
|
||||
bearing -= 360.0f;
|
||||
if (c++ > 3)
|
||||
|
||||
if (c++ > 3) {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
c = 0;
|
||||
while (bearing < 0.0f) {
|
||||
bearing += 360.0f;
|
||||
if (c++ > 3)
|
||||
|
||||
if (c++ > 3) {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
return bearing;
|
||||
|
||||
+22
-16
@@ -1,9 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* Julian Oes <joes@student.ethz.ch>
|
||||
* Lorenz Meier <lm@inf.ethz.ch>
|
||||
* Copyright (C) 2012, 2014 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
|
||||
@@ -42,6 +39,7 @@
|
||||
* @author Thomas Gubler <thomasgubler@student.ethz.ch>
|
||||
* @author Julian Oes <joes@student.ethz.ch>
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
* Additional functions - @author Doug Weibel <douglas.weibel@colorado.edu>
|
||||
*/
|
||||
|
||||
@@ -67,6 +65,14 @@ struct crosstrack_error_s {
|
||||
float bearing; // Bearing in radians to closest point on line/arc
|
||||
} ;
|
||||
|
||||
/* lat/lon are in radians */
|
||||
struct map_projection_reference_s {
|
||||
double lat;
|
||||
double lon;
|
||||
double sin_lat;
|
||||
double cos_lat;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes the map transformation.
|
||||
*
|
||||
@@ -74,7 +80,7 @@ struct crosstrack_error_s {
|
||||
* @param lat in degrees (47.1234567°, not 471234567°)
|
||||
* @param lon in degrees (8.1234567°, not 81234567°)
|
||||
*/
|
||||
__EXPORT void map_projection_init(double lat_0, double lon_0);
|
||||
__EXPORT void map_projection_init(struct map_projection_reference_s *ref, double lat_0, double lon_0);
|
||||
|
||||
/**
|
||||
* Transforms a point in the geographic coordinate system to the local azimuthal equidistant plane
|
||||
@@ -83,7 +89,7 @@ __EXPORT void map_projection_init(double lat_0, double lon_0);
|
||||
* @param lat in degrees (47.1234567°, not 471234567°)
|
||||
* @param lon in degrees (8.1234567°, not 81234567°)
|
||||
*/
|
||||
__EXPORT void map_projection_project(double lat, double lon, float *x, float *y);
|
||||
__EXPORT void map_projection_project(struct map_projection_reference_s *ref, double lat, double lon, float *x, float *y);
|
||||
|
||||
/**
|
||||
* Transforms a point in the local azimuthal equidistant plane to the geographic coordinate system
|
||||
@@ -93,7 +99,7 @@ __EXPORT void map_projection_project(double lat, double lon, float *x, float *y)
|
||||
* @param lat in degrees (47.1234567°, not 471234567°)
|
||||
* @param lon in degrees (8.1234567°, not 81234567°)
|
||||
*/
|
||||
__EXPORT void map_projection_reproject(float x, float y, double *lat, double *lon);
|
||||
__EXPORT void map_projection_reproject(struct map_projection_reference_s *ref, float x, float y, double *lat, double *lon);
|
||||
|
||||
/**
|
||||
* Returns the distance to the next waypoint in meters.
|
||||
@@ -115,30 +121,30 @@ __EXPORT float get_distance_to_next_waypoint(double lat_now, double lon_now, dou
|
||||
*/
|
||||
__EXPORT float get_bearing_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next);
|
||||
|
||||
__EXPORT void get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float* v_n, float* v_e);
|
||||
__EXPORT void get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float *v_n, float *v_e);
|
||||
|
||||
__EXPORT void get_vector_to_next_waypoint_fast(double lat_now, double lon_now, double lat_next, double lon_next, float* v_n, float* v_e);
|
||||
__EXPORT void get_vector_to_next_waypoint_fast(double lat_now, double lon_now, double lat_next, double lon_next, float *v_n, float *v_e);
|
||||
|
||||
__EXPORT void add_vector_to_global_position(double lat_now, double lon_now, float v_n, float v_e, double *lat_res, double *lon_res);
|
||||
|
||||
__EXPORT int get_distance_to_line(struct crosstrack_error_s * crosstrack_error, double lat_now, double lon_now, double lat_start, double lon_start, double lat_end, double lon_end);
|
||||
__EXPORT int get_distance_to_line(struct crosstrack_error_s *crosstrack_error, double lat_now, double lon_now, double lat_start, double lon_start, double lat_end, double lon_end);
|
||||
|
||||
__EXPORT int get_distance_to_arc(struct crosstrack_error_s * crosstrack_error, double lat_now, double lon_now, double lat_center, double lon_center,
|
||||
float radius, float arc_start_bearing, float arc_sweep);
|
||||
__EXPORT int get_distance_to_arc(struct crosstrack_error_s *crosstrack_error, double lat_now, double lon_now, double lat_center, double lon_center,
|
||||
float radius, float arc_start_bearing, float arc_sweep);
|
||||
|
||||
/*
|
||||
* Calculate distance in global frame
|
||||
*/
|
||||
__EXPORT float get_distance_to_point_global_wgs84(double lat_now, double lon_now, float alt_now,
|
||||
double lat_next, double lon_next, float alt_next,
|
||||
float *dist_xy, float *dist_z);
|
||||
double lat_next, double lon_next, float alt_next,
|
||||
float *dist_xy, float *dist_z);
|
||||
|
||||
/*
|
||||
* Calculate distance in local frame (NED)
|
||||
*/
|
||||
__EXPORT float mavlink_wpm_distance_to_point_local(float x_now, float y_now, float z_now,
|
||||
float x_next, float y_next, float z_next,
|
||||
float *dist_xy, float *dist_z);
|
||||
float x_next, float y_next, float z_next,
|
||||
float *dist_xy, float *dist_z);
|
||||
|
||||
__EXPORT float _wrap_180(float bearing);
|
||||
__EXPORT float _wrap_360(float bearing);
|
||||
|
||||
@@ -97,6 +97,8 @@ KalmanNav::KalmanNav(SuperBlock *parent, const char *name) :
|
||||
{
|
||||
using namespace math;
|
||||
|
||||
memset(&ref, 0, sizeof(ref));
|
||||
|
||||
F.zero();
|
||||
G.zero();
|
||||
V.zero();
|
||||
@@ -247,11 +249,7 @@ void KalmanNav::update()
|
||||
lat0 = lat;
|
||||
lon0 = lon;
|
||||
alt0 = alt;
|
||||
// XXX map_projection has internal global
|
||||
// states that multiple things could change,
|
||||
// should make map_projection take reference
|
||||
// lat/lon and not have init
|
||||
map_projection_init(lat0, lon0);
|
||||
map_projection_init(&ref, lat0, lon0);
|
||||
_positionInitialized = true;
|
||||
warnx("initialized EKF state with GPS");
|
||||
warnx("vN: %8.4f, vE: %8.4f, vD: %8.4f, lat: %8.4f, lon: %8.4f, alt: %8.4f",
|
||||
@@ -314,7 +312,6 @@ void KalmanNav::updatePublications()
|
||||
// global position publication
|
||||
_pos.timestamp = _pubTimeStamp;
|
||||
_pos.time_gps_usec = _gps.timestamp_position;
|
||||
_pos.global_valid = true;
|
||||
_pos.lat = lat * M_RAD_TO_DEG;
|
||||
_pos.lon = lon * M_RAD_TO_DEG;
|
||||
_pos.alt = float(alt);
|
||||
@@ -327,7 +324,7 @@ void KalmanNav::updatePublications()
|
||||
float x;
|
||||
float y;
|
||||
bool landed = alt < (alt0 + 0.1); // XXX improve?
|
||||
map_projection_project(lat, lon, &x, &y);
|
||||
map_projection_project(&ref, lat, lon, &x, &y);
|
||||
_localPos.timestamp = _pubTimeStamp;
|
||||
_localPos.xy_valid = true;
|
||||
_localPos.z_valid = true;
|
||||
@@ -343,8 +340,8 @@ void KalmanNav::updatePublications()
|
||||
_localPos.xy_global = true;
|
||||
_localPos.z_global = true;
|
||||
_localPos.ref_timestamp = _pubTimeStamp;
|
||||
_localPos.ref_lat = getLatDegE7();
|
||||
_localPos.ref_lon = getLonDegE7();
|
||||
_localPos.ref_lat = lat * M_RAD_TO_DEG;
|
||||
_localPos.ref_lon = lon * M_RAD_TO_DEG;
|
||||
_localPos.ref_alt = 0;
|
||||
_localPos.landed = landed;
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <controllib/block/BlockParam.hpp>
|
||||
#include <uORB/Subscription.hpp>
|
||||
#include <uORB/Publication.hpp>
|
||||
#include <lib/geo/geo.h>
|
||||
|
||||
#include <uORB/topics/vehicle_attitude.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
@@ -164,6 +165,7 @@ protected:
|
||||
// parameters
|
||||
float alt; /**< altitude, meters */
|
||||
double lat0, lon0; /**< reference latitude and longitude */
|
||||
struct map_projection_reference_s ref; /**< local projection reference */
|
||||
float alt0; /**< refeerence altitude (ground height) */
|
||||
control::BlockParamFloat _vGyro; /**< gyro process noise */
|
||||
control::BlockParamFloat _vAccel; /**< accelerometer process noise */
|
||||
|
||||
@@ -407,7 +407,7 @@ const unsigned int loop_interval_alarm = 6500; // loop interval in microseconds
|
||||
vel(2) = gps.vel_d_m_s;
|
||||
}
|
||||
|
||||
} else if (ekf_params.acc_comp == 2 && global_pos.global_valid && hrt_absolute_time() < global_pos.timestamp + 500000) {
|
||||
} else if (ekf_params.acc_comp == 2 && gps.eph_m < 5.0f && global_pos.timestamp != 0 && hrt_absolute_time() < global_pos.timestamp + 20000) {
|
||||
vel_valid = true;
|
||||
if (global_pos_updated) {
|
||||
vel_t = global_pos.timestamp;
|
||||
|
||||
@@ -117,7 +117,7 @@ extern struct system_load_s system_load;
|
||||
#define STICK_ON_OFF_HYSTERESIS_TIME_MS 1000
|
||||
#define STICK_ON_OFF_COUNTER_LIMIT (STICK_ON_OFF_HYSTERESIS_TIME_MS*COMMANDER_MONITORING_LOOPSPERMSEC)
|
||||
|
||||
#define POSITION_TIMEOUT 1000000 /**< consider the local or global position estimate invalid after 1s */
|
||||
#define POSITION_TIMEOUT 30000 /**< consider the local or global position estimate invalid after 30ms */
|
||||
#define RC_TIMEOUT 500000
|
||||
#define DIFFPRESS_TIMEOUT 2000000
|
||||
|
||||
@@ -153,6 +153,7 @@ static bool on_usb_power = false;
|
||||
|
||||
static float takeoff_alt = 5.0f;
|
||||
static int parachute_enabled = 0;
|
||||
static float eph_epv_threshold = 5.0f;
|
||||
|
||||
static struct vehicle_status_s status;
|
||||
static struct actuator_armed_s armed;
|
||||
@@ -194,7 +195,7 @@ void usage(const char *reason);
|
||||
/**
|
||||
* React to commands that are sent e.g. from the mavlink module.
|
||||
*/
|
||||
bool handle_command(struct vehicle_status_s *status, struct vehicle_command_s *cmd, struct actuator_armed_s *armed);
|
||||
bool handle_command(struct vehicle_status_s *status, const struct safety_s *safety, struct vehicle_command_s *cmd, struct actuator_armed_s *armed, struct home_position_s *home, struct vehicle_global_position_s *global_pos, orb_advert_t *home_pub);
|
||||
|
||||
/**
|
||||
* Mainloop of commander.
|
||||
@@ -389,7 +390,7 @@ int disarm()
|
||||
}
|
||||
}
|
||||
|
||||
bool handle_command(struct vehicle_status_s *status, const struct safety_s *safety, struct vehicle_command_s *cmd, struct actuator_armed_s *armed)
|
||||
bool handle_command(struct vehicle_status_s *status, const struct safety_s *safety, struct vehicle_command_s *cmd, struct actuator_armed_s *armed, struct home_position_s *home, struct vehicle_global_position_s *global_pos, orb_advert_t *home_pub)
|
||||
{
|
||||
/* result of the command */
|
||||
enum VEHICLE_CMD_RESULT result = VEHICLE_CMD_RESULT_UNSUPPORTED;
|
||||
@@ -584,6 +585,51 @@ bool handle_command(struct vehicle_status_s *status, const struct safety_s *safe
|
||||
}
|
||||
break;
|
||||
|
||||
case VEHICLE_CMD_DO_SET_HOME: {
|
||||
bool use_current = cmd->param1 > 0.5f;
|
||||
if (use_current) {
|
||||
/* use current position */
|
||||
if (status->condition_global_position_valid) {
|
||||
home->lat = global_pos->lat;
|
||||
home->lon = global_pos->lon;
|
||||
home->alt = global_pos->alt;
|
||||
|
||||
home->timestamp = hrt_absolute_time();
|
||||
|
||||
result = VEHICLE_CMD_RESULT_ACCEPTED;
|
||||
|
||||
} else {
|
||||
result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* use specified position */
|
||||
home->lat = cmd->param5;
|
||||
home->lon = cmd->param6;
|
||||
home->alt = cmd->param7;
|
||||
|
||||
home->timestamp = hrt_absolute_time();
|
||||
|
||||
result = VEHICLE_CMD_RESULT_ACCEPTED;
|
||||
}
|
||||
|
||||
if (result == VEHICLE_CMD_RESULT_ACCEPTED) {
|
||||
warnx("home: lat = %.7f, lon = %.7f, alt = %.2f ", home->lat, home->lon, (double)home->alt);
|
||||
mavlink_log_info(mavlink_fd, "[cmd] home: %.7f, %.7f, %.2f", home->lat, home->lon, (double)home->alt);
|
||||
|
||||
/* announce new home position */
|
||||
if (*home_pub > 0) {
|
||||
orb_publish(ORB_ID(home_position), *home_pub, home);
|
||||
|
||||
} else {
|
||||
*home_pub = orb_advertise(ORB_ID(home_position), home);
|
||||
}
|
||||
|
||||
/* mark home position as set */
|
||||
status->condition_home_position_valid = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case VEHICLE_CMD_PREFLIGHT_REBOOT_SHUTDOWN:
|
||||
case VEHICLE_CMD_PREFLIGHT_CALIBRATION:
|
||||
case VEHICLE_CMD_PREFLIGHT_SET_SENSOR_OFFSETS:
|
||||
@@ -616,6 +662,7 @@ int commander_thread_main(int argc, char *argv[])
|
||||
commander_initialized = false;
|
||||
|
||||
bool arm_tune_played = false;
|
||||
bool was_armed = false;
|
||||
|
||||
/* set parameters */
|
||||
param_t _param_sys_type = param_find("MAV_TYPE");
|
||||
@@ -929,7 +976,45 @@ int commander_thread_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* update condition_global_position_valid */
|
||||
check_valid(global_position.timestamp, POSITION_TIMEOUT, global_position.global_valid, &(status.condition_global_position_valid), &status_changed);
|
||||
/* hysteresis for EPH/EPV */
|
||||
bool eph_epv_good;
|
||||
if (status.condition_global_position_valid) {
|
||||
if (global_position.eph > eph_epv_threshold * 2.0f || global_position.epv > eph_epv_threshold * 2.0f) {
|
||||
eph_epv_good = false;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (global_position.eph < eph_epv_threshold && global_position.epv < eph_epv_threshold) {
|
||||
eph_epv_good = true;
|
||||
}
|
||||
}
|
||||
check_valid(global_position.timestamp, POSITION_TIMEOUT, eph_epv_good, &(status.condition_global_position_valid), &status_changed);
|
||||
|
||||
/* check if GPS fix is ok */
|
||||
|
||||
/* update home position */
|
||||
if (!status.condition_home_position_valid && status.condition_global_position_valid && !armed.armed &&
|
||||
(global_position.eph < eph_epv_threshold) && (global_position.epv < eph_epv_threshold)) {
|
||||
|
||||
home.lat = global_position.lat;
|
||||
home.lon = global_position.lon;
|
||||
home.alt = global_position.alt;
|
||||
|
||||
warnx("home: lat = %.7f, lon = %.7f, alt = %.2f ", home.lat, home.lon, (double)home.alt);
|
||||
mavlink_log_info(mavlink_fd, "[cmd] home: %.7f, %.7f, %.2f", home.lat, home.lon, (double)home.alt);
|
||||
|
||||
/* announce new home position */
|
||||
if (home_pub > 0) {
|
||||
orb_publish(ORB_ID(home_position), home_pub, &home);
|
||||
|
||||
} else {
|
||||
home_pub = orb_advertise(ORB_ID(home_position), &home);
|
||||
}
|
||||
|
||||
/* mark home position as set */
|
||||
status.condition_home_position_valid = true;
|
||||
tune_positive(true);
|
||||
}
|
||||
|
||||
/* update local position estimate */
|
||||
orb_check(local_position_sub, &updated);
|
||||
@@ -940,7 +1025,7 @@ int commander_thread_main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* update condition_local_position_valid and condition_local_altitude_valid */
|
||||
check_valid(local_position.timestamp, POSITION_TIMEOUT, local_position.xy_valid, &(status.condition_local_position_valid), &status_changed);
|
||||
check_valid(local_position.timestamp, POSITION_TIMEOUT, local_position.xy_valid && eph_epv_good, &(status.condition_local_position_valid), &status_changed);
|
||||
check_valid(local_position.timestamp, POSITION_TIMEOUT, local_position.z_valid, &(status.condition_local_altitude_valid), &status_changed);
|
||||
|
||||
static bool published_condition_landed_fw = false;
|
||||
@@ -1084,45 +1169,6 @@ int commander_thread_main(int argc, char *argv[])
|
||||
|
||||
if (updated) {
|
||||
orb_copy(ORB_ID(vehicle_gps_position), gps_sub, &gps_position);
|
||||
/* check if GPS fix is ok */
|
||||
float hdop_threshold_m = 4.0f;
|
||||
float vdop_threshold_m = 8.0f;
|
||||
|
||||
/*
|
||||
* If horizontal dilution of precision (hdop / eph)
|
||||
* and vertical diluation of precision (vdop / epv)
|
||||
* are below a certain threshold (e.g. 4 m), AND
|
||||
* home position is not yet set AND the last GPS
|
||||
* GPS measurement is not older than two seconds AND
|
||||
* the system is currently not armed, set home
|
||||
* position to the current position.
|
||||
*/
|
||||
|
||||
if (!status.condition_home_position_valid && gps_position.fix_type >= 3 &&
|
||||
(gps_position.eph_m < hdop_threshold_m) && (gps_position.epv_m < vdop_threshold_m) &&
|
||||
(hrt_absolute_time() < gps_position.timestamp_position + POSITION_TIMEOUT) && !armed.armed
|
||||
&& global_position.global_valid) {
|
||||
|
||||
/* copy position data to uORB home message, store it locally as well */
|
||||
home.lat = global_position.lat;
|
||||
home.lon = global_position.lon;
|
||||
home.alt = global_position.alt;
|
||||
|
||||
warnx("home: lat = %.7f, lon = %.7f, alt = %.4f ", home.lat, home.lon, (double)home.alt);
|
||||
mavlink_log_info(mavlink_fd, "[cmd] home: %.7f, %.7f, %.4f", home.lat, home.lon, (double)home.alt);
|
||||
|
||||
/* announce new home position */
|
||||
if (home_pub > 0) {
|
||||
orb_publish(ORB_ID(home_position), home_pub, &home);
|
||||
|
||||
} else {
|
||||
home_pub = orb_advertise(ORB_ID(home_position), &home);
|
||||
}
|
||||
|
||||
/* mark home position as set */
|
||||
status.condition_home_position_valid = true;
|
||||
tune_positive(true);
|
||||
}
|
||||
}
|
||||
|
||||
/* start RC input check */
|
||||
@@ -1310,7 +1356,7 @@ int commander_thread_main(int argc, char *argv[])
|
||||
orb_copy(ORB_ID(vehicle_command), cmd_sub, &cmd);
|
||||
|
||||
/* handle it */
|
||||
if (handle_command(&status, &safety, &cmd, &armed))
|
||||
if (handle_command(&status, &safety, &cmd, &armed, &home, &global_position, &home_pub))
|
||||
status_changed = true;
|
||||
}
|
||||
|
||||
@@ -1325,7 +1371,32 @@ int commander_thread_main(int argc, char *argv[])
|
||||
if (arming_state_changed) {
|
||||
status_changed = true;
|
||||
mavlink_log_info(mavlink_fd, "[cmd] arming state: %s", arming_states_str[status.arming_state]);
|
||||
|
||||
/* update home position on arming if at least 2s from commander start spent to avoid setting home on in-air restart */
|
||||
if (armed.armed && !was_armed && hrt_absolute_time() > start_time + 2000000 && status.condition_global_position_valid &&
|
||||
(global_position.eph < eph_epv_threshold) && (global_position.epv < eph_epv_threshold)) {
|
||||
|
||||
// TODO remove code duplication
|
||||
home.lat = global_position.lat;
|
||||
home.lon = global_position.lon;
|
||||
home.alt = global_position.alt;
|
||||
|
||||
warnx("home: lat = %.7f, lon = %.7f, alt = %.2f ", home.lat, home.lon, (double)home.alt);
|
||||
mavlink_log_info(mavlink_fd, "[cmd] home: %.7f, %.7f, %.2f", home.lat, home.lon, (double)home.alt);
|
||||
|
||||
/* announce new home position */
|
||||
if (home_pub > 0) {
|
||||
orb_publish(ORB_ID(home_position), home_pub, &home);
|
||||
|
||||
} else {
|
||||
home_pub = orb_advertise(ORB_ID(home_position), &home);
|
||||
}
|
||||
|
||||
/* mark home position as set */
|
||||
status.condition_home_position_valid = true;
|
||||
}
|
||||
}
|
||||
was_armed = armed.armed;
|
||||
|
||||
if (main_state_changed) {
|
||||
status_changed = true;
|
||||
|
||||
@@ -177,6 +177,8 @@ private:
|
||||
struct sensor_combined_s _sensor_combined;
|
||||
#endif
|
||||
|
||||
struct map_projection_reference_s _pos_ref;
|
||||
|
||||
float _baro_ref; /**< barometer reference altitude */
|
||||
float _baro_gps_offset; /**< offset between GPS and baro */
|
||||
|
||||
@@ -821,7 +823,7 @@ FixedwingEstimator::task_main()
|
||||
_baro_gps_offset = _baro_ref - _local_pos.ref_alt;
|
||||
|
||||
// XXX this is not multithreading safe
|
||||
map_projection_init(lat, lon);
|
||||
map_projection_init(&_pos_ref, lat, lon);
|
||||
mavlink_log_info(_mavlink_fd, "[position estimator] init ref: lat=%.7f, lon=%.7f, alt=%.2f", lat, lon, alt);
|
||||
|
||||
_gps_initialized = true;
|
||||
@@ -1042,18 +1044,14 @@ FixedwingEstimator::task_main()
|
||||
|
||||
_global_pos.timestamp = _local_pos.timestamp;
|
||||
|
||||
_global_pos.baro_valid = true;
|
||||
_global_pos.global_valid = true;
|
||||
|
||||
if (_local_pos.xy_global) {
|
||||
double est_lat, est_lon;
|
||||
map_projection_reproject(_local_pos.x, _local_pos.y, &est_lat, &est_lon);
|
||||
map_projection_reproject(&_pos_ref, _local_pos.x, _local_pos.y, &est_lat, &est_lon);
|
||||
_global_pos.lat = est_lat;
|
||||
_global_pos.lon = est_lon;
|
||||
_global_pos.time_gps_usec = _gps.time_gps_usec;
|
||||
}
|
||||
|
||||
/* set valid values even if position is not valid */
|
||||
if (_local_pos.v_xy_valid) {
|
||||
_global_pos.vel_n = _local_pos.vx;
|
||||
_global_pos.vel_e = _local_pos.vy;
|
||||
@@ -1065,16 +1063,15 @@ FixedwingEstimator::task_main()
|
||||
/* local pos alt is negative, change sign and add alt offset */
|
||||
_global_pos.alt = _local_pos.ref_alt + (-_local_pos.z);
|
||||
|
||||
if (_local_pos.z_valid) {
|
||||
_global_pos.baro_alt = _local_pos.ref_alt - _baro_gps_offset - _local_pos.z;
|
||||
}
|
||||
|
||||
if (_local_pos.v_z_valid) {
|
||||
_global_pos.vel_d = _local_pos.vz;
|
||||
}
|
||||
|
||||
_global_pos.yaw = _local_pos.yaw;
|
||||
|
||||
_global_pos.eph = _gps.eph_m;
|
||||
_global_pos.epv = _gps.epv_m;
|
||||
|
||||
_global_pos.timestamp = _local_pos.timestamp;
|
||||
|
||||
/* lazily publish the global position only once available */
|
||||
|
||||
@@ -245,6 +245,7 @@ MavlinkReceiver::handle_message_optical_flow(mavlink_message_t *msg)
|
||||
memset(&f, 0, sizeof(f));
|
||||
|
||||
f.timestamp = hrt_absolute_time();
|
||||
f.flow_timestamp = flow.time_usec;
|
||||
f.flow_raw_x = flow.flow_x;
|
||||
f.flow_raw_y = flow.flow_y;
|
||||
f.flow_comp_x_m = flow.flow_comp_m_x;
|
||||
@@ -739,7 +740,6 @@ MavlinkReceiver::handle_message_hil_state_quaternion(mavlink_message_t *msg)
|
||||
memset(&hil_global_pos, 0, sizeof(hil_global_pos));
|
||||
|
||||
hil_global_pos.timestamp = timestamp;
|
||||
hil_global_pos.global_valid = true;
|
||||
hil_global_pos.lat = hil_state.lat;
|
||||
hil_global_pos.lon = hil_state.lon;
|
||||
hil_global_pos.alt = hil_state.alt / 1000.0f;
|
||||
@@ -747,6 +747,8 @@ MavlinkReceiver::handle_message_hil_state_quaternion(mavlink_message_t *msg)
|
||||
hil_global_pos.vel_e = hil_state.vy / 100.0f;
|
||||
hil_global_pos.vel_d = hil_state.vz / 100.0f;
|
||||
hil_global_pos.yaw = hil_attitude.yaw;
|
||||
hil_global_pos.eph = 2.0f;
|
||||
hil_global_pos.epv = 4.0f;
|
||||
|
||||
if (_global_pos_pub < 0) {
|
||||
_global_pos_pub = orb_advertise(ORB_ID(vehicle_global_position), &hil_global_pos);
|
||||
@@ -758,19 +760,22 @@ MavlinkReceiver::handle_message_hil_state_quaternion(mavlink_message_t *msg)
|
||||
|
||||
/* local position */
|
||||
{
|
||||
double lat = hil_state.lat * 1e-7;
|
||||
double lon = hil_state.lon * 1e-7;
|
||||
|
||||
if (!_hil_local_proj_inited) {
|
||||
_hil_local_proj_inited = true;
|
||||
_hil_local_alt0 = hil_state.alt / 1000.0f;
|
||||
map_projection_init(hil_state.lat, hil_state.lon);
|
||||
map_projection_init(&_hil_local_proj_ref, hil_state.lat, hil_state.lon);
|
||||
hil_local_pos.ref_timestamp = timestamp;
|
||||
hil_local_pos.ref_lat = hil_state.lat;
|
||||
hil_local_pos.ref_lon = hil_state.lon;
|
||||
hil_local_pos.ref_lat = lat;
|
||||
hil_local_pos.ref_lon = lon;
|
||||
hil_local_pos.ref_alt = _hil_local_alt0;
|
||||
}
|
||||
|
||||
float x;
|
||||
float y;
|
||||
map_projection_project(hil_state.lat * 1e-7, hil_state.lon * 1e-7, &x, &y);
|
||||
map_projection_project(&_hil_local_proj_ref, lat, lon, &x, &y);
|
||||
hil_local_pos.timestamp = timestamp;
|
||||
hil_local_pos.xy_valid = true;
|
||||
hil_local_pos.z_valid = true;
|
||||
|
||||
@@ -142,4 +142,5 @@ private:
|
||||
uint64_t _old_timestamp;
|
||||
bool _hil_local_proj_inited;
|
||||
float _hil_local_alt0;
|
||||
struct map_projection_reference_s _hil_local_proj_ref;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -177,7 +177,7 @@ private:
|
||||
class Mission _mission;
|
||||
|
||||
bool _mission_item_valid; /**< current mission item valid */
|
||||
bool _global_pos_valid; /**< track changes of global_position.global_valid flag */
|
||||
bool _global_pos_valid; /**< track changes of global_position */
|
||||
bool _reset_loiter_pos; /**< if true then loiter position should be set to current position */
|
||||
bool _waypoint_position_reached;
|
||||
bool _waypoint_yaw_reached;
|
||||
@@ -781,13 +781,11 @@ Navigator::task_main()
|
||||
if (_control_mode.flag_armed && _control_mode.flag_control_auto_enabled) {
|
||||
_pos_sp_triplet_updated = true;
|
||||
|
||||
if (myState == NAV_STATE_LAND && _global_pos.global_valid && !_global_pos_valid) {
|
||||
if (myState == NAV_STATE_LAND && !_global_pos_valid) {
|
||||
/* got global position when landing, update setpoint */
|
||||
start_land();
|
||||
}
|
||||
|
||||
_global_pos_valid = _global_pos.global_valid;
|
||||
|
||||
/* check if waypoint has been reached in MISSION, RTL and LAND modes */
|
||||
if (myState == NAV_STATE_MISSION || myState == NAV_STATE_RTL || myState == NAV_STATE_LAND) {
|
||||
if (check_mission_item_reached()) {
|
||||
@@ -812,6 +810,8 @@ Navigator::task_main()
|
||||
}
|
||||
}
|
||||
|
||||
_global_pos_valid = _vstatus.condition_global_position_valid;
|
||||
|
||||
/* publish position setpoint triplet if updated */
|
||||
if (_pos_sp_triplet_updated) {
|
||||
_pos_sp_triplet_updated = false;
|
||||
@@ -857,9 +857,9 @@ Navigator::start()
|
||||
void
|
||||
Navigator::status()
|
||||
{
|
||||
warnx("Global position is %svalid", _global_pos.global_valid ? "" : "in");
|
||||
warnx("Global position: %svalid", _global_pos_valid ? "" : "in");
|
||||
|
||||
if (_global_pos.global_valid) {
|
||||
if (_global_pos_valid) {
|
||||
warnx("Longitude %5.5f degrees, latitude %5.5f degrees", _global_pos.lon, _global_pos.lat);
|
||||
warnx("Altitude %5.5f meters, altitude above home %5.5f meters",
|
||||
(double)_global_pos.alt, (double)(_global_pos.alt - _home_pos.alt));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2013 Anton Babushkin. All rights reserved.
|
||||
* Author: Anton Babushkin <rk3dov@gmail.com>
|
||||
* Copyright (C) 2013, 2014 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
|
||||
@@ -35,6 +34,8 @@
|
||||
/**
|
||||
* @file position_estimator_inav_main.c
|
||||
* Model-identification based position estimator for multirotors
|
||||
*
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
@@ -57,6 +58,7 @@
|
||||
#include <uORB/topics/vehicle_local_position.h>
|
||||
#include <uORB/topics/vehicle_global_position.h>
|
||||
#include <uORB/topics/vehicle_gps_position.h>
|
||||
#include <uORB/topics/home_position.h>
|
||||
#include <uORB/topics/optical_flow.h>
|
||||
#include <mavlink/mavlink_log.h>
|
||||
#include <poll.h>
|
||||
@@ -95,8 +97,9 @@ static void usage(const char *reason);
|
||||
*/
|
||||
static void usage(const char *reason)
|
||||
{
|
||||
if (reason)
|
||||
if (reason) {
|
||||
fprintf(stderr, "%s\n", reason);
|
||||
}
|
||||
|
||||
fprintf(stderr, "usage: position_estimator_inav {start|stop|status} [-v]\n\n");
|
||||
exit(1);
|
||||
@@ -112,8 +115,9 @@ static void usage(const char *reason)
|
||||
*/
|
||||
int position_estimator_inav_main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
if (argc < 1) {
|
||||
usage("missing command");
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "start")) {
|
||||
if (thread_running) {
|
||||
@@ -125,8 +129,9 @@ int position_estimator_inav_main(int argc, char *argv[])
|
||||
verbose_mode = false;
|
||||
|
||||
if (argc > 1)
|
||||
if (!strcmp(argv[2], "-v"))
|
||||
if (!strcmp(argv[2], "-v")) {
|
||||
verbose_mode = true;
|
||||
}
|
||||
|
||||
thread_should_exit = false;
|
||||
position_estimator_inav_task = task_spawn_cmd("position_estimator_inav",
|
||||
@@ -163,16 +168,19 @@ int position_estimator_inav_main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void write_debug_log(const char *msg, float dt, float x_est[3], float y_est[3], float z_est[3], float corr_acc[3], float corr_gps[3][2], float w_xy_gps_p, float w_xy_gps_v) {
|
||||
void write_debug_log(const char *msg, float dt, float x_est[3], float y_est[3], float z_est[3], float x_est_prev[3], float y_est_prev[3], float z_est_prev[3], float corr_acc[3], float corr_gps[3][2], float w_xy_gps_p, float w_xy_gps_v)
|
||||
{
|
||||
FILE *f = fopen("/fs/microsd/inav.log", "a");
|
||||
|
||||
if (f) {
|
||||
char *s = malloc(256);
|
||||
unsigned n = snprintf(s, 256, "%llu %s\n\tdt=%.5f x_est=[%.5f %.5f %.5f] y_est=[%.5f %.5f %.5f] z_est=[%.5f %.5f %.5f]\n", hrt_absolute_time(), msg, dt, x_est[0], x_est[1], x_est[2], y_est[0], y_est[1], y_est[2], z_est[0], z_est[1], z_est[2]);
|
||||
unsigned n = snprintf(s, 256, "%llu %s\n\tdt=%.5f x_est=[%.5f %.5f %.5f] y_est=[%.5f %.5f %.5f] z_est=[%.5f %.5f %.5f] x_est_prev=[%.5f %.5f %.5f] y_est_prev=[%.5f %.5f %.5f] z_est_prev=[%.5f %.5f %.5f]\n", hrt_absolute_time(), msg, dt, x_est[0], x_est[1], x_est[2], y_est[0], y_est[1], y_est[2], z_est[0], z_est[1], z_est[2], x_est_prev[0], x_est_prev[1], x_est_prev[2], y_est_prev[0], y_est_prev[1], y_est_prev[2], z_est_prev[0], z_est_prev[1], z_est_prev[2]);
|
||||
fwrite(s, 1, n, f);
|
||||
n = snprintf(s, 256, "\tacc_corr=[%.5f %.5f %.5f] gps_pos_corr=[%.5f %.5f %.5f] gps_vel_corr=[%.5f %.5f %.5f] w_xy_gps_p=%.5f w_xy_gps_v=%.5f\n", corr_acc[0], corr_acc[1], corr_acc[2], corr_gps[0][0], corr_gps[1][0], corr_gps[2][0], corr_gps[0][1], corr_gps[1][1], corr_gps[2][1], w_xy_gps_p, w_xy_gps_v);
|
||||
fwrite(s, 1, n, f);
|
||||
free(s);
|
||||
}
|
||||
|
||||
fsync(fileno(f));
|
||||
fclose(f);
|
||||
}
|
||||
@@ -191,6 +199,11 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
float y_est[3] = { 0.0f, 0.0f, 0.0f };
|
||||
float z_est[3] = { 0.0f, 0.0f, 0.0f };
|
||||
|
||||
float x_est_prev[3], y_est_prev[3], z_est_prev[3];
|
||||
memset(x_est_prev, 0, sizeof(x_est_prev));
|
||||
memset(y_est_prev, 0, sizeof(y_est_prev));
|
||||
memset(z_est_prev, 0, sizeof(z_est_prev));
|
||||
|
||||
int baro_init_cnt = 0;
|
||||
int baro_init_num = 200;
|
||||
float baro_offset = 0.0f; // baro offset for reference altitude, initialized on start, then adjusted
|
||||
@@ -206,6 +219,9 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
bool ref_inited = false;
|
||||
hrt_abstime ref_init_start = 0;
|
||||
const hrt_abstime ref_init_delay = 1000000; // wait for 1s after 3D fix
|
||||
struct map_projection_reference_s ref;
|
||||
memset(&ref, 0, sizeof(ref));
|
||||
hrt_abstime home_timestamp = 0;
|
||||
|
||||
uint16_t accel_updates = 0;
|
||||
uint16_t baro_updates = 0;
|
||||
@@ -238,7 +254,11 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
float corr_flow[] = { 0.0f, 0.0f }; // N E
|
||||
float w_flow = 0.0f;
|
||||
|
||||
static float min_eph_epv = 2.0f; // min EPH/EPV, used for weight calculation
|
||||
static float max_eph_epv = 10.0f; // max EPH/EPV acceptable for estimation
|
||||
|
||||
float sonar_prev = 0.0f;
|
||||
hrt_abstime flow_prev = 0; // time of last flow measurement
|
||||
hrt_abstime sonar_time = 0; // time of last sonar measurement (not filtered)
|
||||
hrt_abstime sonar_valid_time = 0; // time of last sonar measurement used for correction (filtered)
|
||||
hrt_abstime xy_src_time = 0; // time of last available position data
|
||||
@@ -257,6 +277,8 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
memset(&sensor, 0, sizeof(sensor));
|
||||
struct vehicle_gps_position_s gps;
|
||||
memset(&gps, 0, sizeof(gps));
|
||||
struct home_position_s home;
|
||||
memset(&home, 0, sizeof(home));
|
||||
struct vehicle_attitude_s att;
|
||||
memset(&att, 0, sizeof(att));
|
||||
struct vehicle_local_position_s local_pos;
|
||||
@@ -274,10 +296,11 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
int vehicle_attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude));
|
||||
int optical_flow_sub = orb_subscribe(ORB_ID(optical_flow));
|
||||
int vehicle_gps_position_sub = orb_subscribe(ORB_ID(vehicle_gps_position));
|
||||
int home_position_sub = orb_subscribe(ORB_ID(home_position));
|
||||
|
||||
/* advertise */
|
||||
orb_advert_t vehicle_local_position_pub = orb_advertise(ORB_ID(vehicle_local_position), &local_pos);
|
||||
orb_advert_t vehicle_global_position_pub = orb_advertise(ORB_ID(vehicle_global_position), &global_pos);
|
||||
orb_advert_t vehicle_global_position_pub = -1;
|
||||
|
||||
struct position_estimator_inav_params params;
|
||||
struct position_estimator_inav_param_handles pos_inav_param_handles;
|
||||
@@ -325,7 +348,6 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
mavlink_log_info(mavlink_fd, "[inav] baro offs: %.2f", baro_offset);
|
||||
local_pos.z_valid = true;
|
||||
local_pos.v_z_valid = true;
|
||||
global_pos.baro_valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -425,6 +447,10 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
if (updated) {
|
||||
orb_copy(ORB_ID(optical_flow), optical_flow_sub, &flow);
|
||||
|
||||
/* calculate time from previous update */
|
||||
float flow_dt = flow_prev > 0 ? (flow.flow_timestamp - flow_prev) * 1e-6f : 0.1f;
|
||||
flow_prev = flow.flow_timestamp;
|
||||
|
||||
if (flow.ground_distance_m > 0.31f && flow.ground_distance_m < 4.0f && att.R[2][2] > 0.7 && flow.ground_distance_m != sonar_prev) {
|
||||
sonar_time = t;
|
||||
sonar_prev = flow.ground_distance_m;
|
||||
@@ -475,10 +501,10 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
flow_accurate = fabsf(body_v_est[1] / flow_dist - att.rollspeed) < max_flow &&
|
||||
fabsf(body_v_est[0] / flow_dist + att.pitchspeed) < max_flow;
|
||||
|
||||
/* convert raw flow to angular flow */
|
||||
/* convert raw flow to angular flow (rad/s) */
|
||||
float flow_ang[2];
|
||||
flow_ang[0] = flow.flow_raw_x * params.flow_k;
|
||||
flow_ang[1] = flow.flow_raw_y * params.flow_k;
|
||||
flow_ang[0] = flow.flow_raw_x * params.flow_k / 1000.0f / flow_dt;
|
||||
flow_ang[1] = flow.flow_raw_y * params.flow_k / 1000.0f / flow_dt;
|
||||
/* flow measurements vector */
|
||||
float flow_m[3];
|
||||
flow_m[0] = -flow_ang[0] * flow_dist;
|
||||
@@ -503,8 +529,9 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
|
||||
/* if flow is not accurate, reduce weight for it */
|
||||
// TODO make this more fuzzy
|
||||
if (!flow_accurate)
|
||||
if (!flow_accurate) {
|
||||
w_flow *= 0.05f;
|
||||
}
|
||||
|
||||
flow_valid = true;
|
||||
|
||||
@@ -516,32 +543,73 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
flow_updates++;
|
||||
}
|
||||
|
||||
/* home position */
|
||||
orb_check(home_position_sub, &updated);
|
||||
|
||||
if (updated) {
|
||||
orb_copy(ORB_ID(home_position), home_position_sub, &home);
|
||||
|
||||
if (home.timestamp != home_timestamp) {
|
||||
home_timestamp = home.timestamp;
|
||||
|
||||
double est_lat, est_lon;
|
||||
float est_alt;
|
||||
|
||||
if (ref_inited) {
|
||||
/* calculate current estimated position in global frame */
|
||||
est_alt = local_pos.ref_alt - local_pos.z;
|
||||
map_projection_reproject(&ref, local_pos.x, local_pos.y, &est_lat, &est_lon);
|
||||
}
|
||||
|
||||
/* update reference */
|
||||
map_projection_init(&ref, home.lat, home.lon);
|
||||
|
||||
/* update baro offset */
|
||||
baro_offset += home.alt - local_pos.ref_alt;
|
||||
|
||||
local_pos.ref_lat = home.lat;
|
||||
local_pos.ref_lon = home.lon;
|
||||
local_pos.ref_alt = home.alt;
|
||||
local_pos.ref_timestamp = home.timestamp;
|
||||
|
||||
if (ref_inited) {
|
||||
/* reproject position estimate with new reference */
|
||||
map_projection_project(&ref, est_lat, est_lon, &x_est[0], &y_est[0]);
|
||||
z_est[0] = -(est_alt - local_pos.ref_alt);
|
||||
}
|
||||
|
||||
ref_inited = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* vehicle GPS position */
|
||||
orb_check(vehicle_gps_position_sub, &updated);
|
||||
|
||||
if (updated) {
|
||||
orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_position_sub, &gps);
|
||||
|
||||
if (gps.fix_type >= 3) {
|
||||
/* hysteresis for GPS quality */
|
||||
if (gps_valid) {
|
||||
if (gps.eph_m > 10.0f || gps.epv_m > 20.0f) {
|
||||
gps_valid = false;
|
||||
mavlink_log_info(mavlink_fd, "[inav] GPS signal lost");
|
||||
}
|
||||
bool reset_est = false;
|
||||
|
||||
} else {
|
||||
if (gps.eph_m < 5.0f && gps.epv_m < 10.0f) {
|
||||
gps_valid = true;
|
||||
mavlink_log_info(mavlink_fd, "[inav] GPS signal found");
|
||||
}
|
||||
/* hysteresis for GPS quality */
|
||||
if (gps_valid) {
|
||||
if (gps.eph_m > max_eph_epv * 1.5f || gps.epv_m > max_eph_epv * 1.5f || gps.fix_type < 3) {
|
||||
gps_valid = false;
|
||||
mavlink_log_info(mavlink_fd, "[inav] GPS signal lost");
|
||||
}
|
||||
|
||||
} else {
|
||||
gps_valid = false;
|
||||
if (gps.eph_m < max_eph_epv && gps.epv_m < max_eph_epv && gps.fix_type >= 3) {
|
||||
gps_valid = true;
|
||||
reset_est = true;
|
||||
mavlink_log_info(mavlink_fd, "[inav] GPS signal found");
|
||||
}
|
||||
}
|
||||
|
||||
if (gps_valid) {
|
||||
double lat = gps.lat * 1e-7;
|
||||
double lon = gps.lon * 1e-7;
|
||||
float alt = gps.alt * 1e-3;
|
||||
|
||||
/* initialize reference position if needed */
|
||||
if (!ref_inited) {
|
||||
if (ref_init_start == 0) {
|
||||
@@ -549,18 +617,25 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
|
||||
} else if (t > ref_init_start + ref_init_delay) {
|
||||
ref_inited = true;
|
||||
/* reference GPS position */
|
||||
double lat = gps.lat * 1e-7;
|
||||
double lon = gps.lon * 1e-7;
|
||||
float alt = gps.alt * 1e-3;
|
||||
/* update baro offset */
|
||||
baro_offset -= z_est[0];
|
||||
|
||||
local_pos.ref_lat = gps.lat;
|
||||
local_pos.ref_lon = gps.lon;
|
||||
local_pos.ref_alt = alt + z_est[0];
|
||||
/* set position estimate to (0, 0, 0), use GPS velocity for XY */
|
||||
x_est[0] = 0.0f;
|
||||
x_est[1] = gps.vel_n_m_s;
|
||||
x_est[2] = accel_NED[0];
|
||||
y_est[0] = 0.0f;
|
||||
y_est[1] = gps.vel_e_m_s;
|
||||
z_est[0] = 0.0f;
|
||||
y_est[2] = accel_NED[1];
|
||||
|
||||
local_pos.ref_lat = lat;
|
||||
local_pos.ref_lon = lon;
|
||||
local_pos.ref_alt = alt;
|
||||
local_pos.ref_timestamp = t;
|
||||
|
||||
/* initialize projection */
|
||||
map_projection_init(lat, lon);
|
||||
map_projection_init(&ref, lat, lon);
|
||||
warnx("init ref: lat=%.7f, lon=%.7f, alt=%.2f", lat, lon, alt);
|
||||
mavlink_log_info(mavlink_fd, "[inav] init ref: lat=%.7f, lon=%.7f, alt=%.2f", lat, lon, alt);
|
||||
}
|
||||
@@ -569,11 +644,22 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
if (ref_inited) {
|
||||
/* project GPS lat lon to plane */
|
||||
float gps_proj[2];
|
||||
map_projection_project(gps.lat * 1e-7, gps.lon * 1e-7, &(gps_proj[0]), &(gps_proj[1]));
|
||||
map_projection_project(&ref, lat, lon, &(gps_proj[0]), &(gps_proj[1]));
|
||||
|
||||
/* reset position estimate when GPS becomes good */
|
||||
if (reset_est) {
|
||||
x_est[0] = gps_proj[0];
|
||||
x_est[1] = gps.vel_n_m_s;
|
||||
x_est[2] = accel_NED[0];
|
||||
y_est[0] = gps_proj[1];
|
||||
y_est[1] = gps.vel_e_m_s;
|
||||
y_est[2] = accel_NED[1];
|
||||
}
|
||||
|
||||
/* calculate correction for position */
|
||||
corr_gps[0][0] = gps_proj[0] - x_est[0];
|
||||
corr_gps[1][0] = gps_proj[1] - y_est[0];
|
||||
corr_gps[2][0] = local_pos.ref_alt - gps.alt * 1e-3 - z_est[0];
|
||||
corr_gps[2][0] = local_pos.ref_alt - alt - z_est[0];
|
||||
|
||||
/* calculate correction for velocity */
|
||||
if (gps.vel_ned_valid) {
|
||||
@@ -587,8 +673,8 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
corr_gps[2][1] = 0.0f;
|
||||
}
|
||||
|
||||
w_gps_xy = 2.0f / fmaxf(2.0f, gps.eph_m);
|
||||
w_gps_z = 4.0f / fmaxf(4.0f, gps.epv_m);
|
||||
w_gps_xy = min_eph_epv / fmaxf(min_eph_epv, gps.eph_m);
|
||||
w_gps_z = min_eph_epv / fmaxf(min_eph_epv, gps.epv_m);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -704,23 +790,34 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
/* inertial filter prediction for altitude */
|
||||
inertial_filter_predict(dt, z_est);
|
||||
|
||||
if (!(isfinite(z_est[0]) && isfinite(z_est[1]) && isfinite(z_est[2]))) {
|
||||
write_debug_log("BAD ESTIMATE AFTER Z PREDICTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev, corr_acc, corr_gps, w_xy_gps_p, w_xy_gps_v);
|
||||
memcpy(z_est, z_est_prev, sizeof(z_est));
|
||||
}
|
||||
|
||||
/* inertial filter correction for altitude */
|
||||
inertial_filter_correct(corr_baro, dt, z_est, 0, params.w_z_baro);
|
||||
inertial_filter_correct(corr_gps[2][0], dt, z_est, 0, w_z_gps_p);
|
||||
inertial_filter_correct(corr_acc[2], dt, z_est, 2, params.w_z_acc);
|
||||
|
||||
float x_est_prev[3], y_est_prev[3];
|
||||
if (!(isfinite(z_est[0]) && isfinite(z_est[1]) && isfinite(z_est[2]))) {
|
||||
write_debug_log("BAD ESTIMATE AFTER Z CORRECTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev, corr_acc, corr_gps, w_xy_gps_p, w_xy_gps_v);
|
||||
memcpy(z_est, z_est_prev, sizeof(z_est));
|
||||
memset(corr_acc, 0, sizeof(corr_acc));
|
||||
memset(corr_gps, 0, sizeof(corr_gps));
|
||||
corr_baro = 0;
|
||||
|
||||
memcpy(x_est_prev, x_est, sizeof(x_est));
|
||||
memcpy(y_est_prev, y_est, sizeof(y_est));
|
||||
} else {
|
||||
memcpy(z_est_prev, z_est, sizeof(z_est));
|
||||
}
|
||||
|
||||
if (can_estimate_xy) {
|
||||
/* inertial filter prediction for position */
|
||||
inertial_filter_predict(dt, x_est);
|
||||
inertial_filter_predict(dt, y_est);
|
||||
|
||||
if (!isfinite(x_est[0]) || !isfinite(y_est[0])) {
|
||||
write_debug_log("BAD ESTIMATE AFTER PREDICTION", dt, x_est, y_est, z_est, corr_acc, corr_gps, w_xy_gps_p, w_xy_gps_v);
|
||||
if (!(isfinite(x_est[0]) && isfinite(x_est[1]) && isfinite(x_est[2]) && isfinite(y_est[0]) && isfinite(y_est[1]) && isfinite(y_est[2]))) {
|
||||
write_debug_log("BAD ESTIMATE AFTER PREDICTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev, corr_acc, corr_gps, w_xy_gps_p, w_xy_gps_v);
|
||||
memcpy(x_est, x_est_prev, sizeof(x_est));
|
||||
memcpy(y_est, y_est_prev, sizeof(y_est));
|
||||
}
|
||||
@@ -744,13 +841,17 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (!isfinite(x_est[0]) || !isfinite(y_est[0])) {
|
||||
write_debug_log("BAD ESTIMATE AFTER CORRECTION", dt, x_est, y_est, z_est, corr_acc, corr_gps, w_xy_gps_p, w_xy_gps_v);
|
||||
if (!(isfinite(x_est[0]) && isfinite(x_est[1]) && isfinite(x_est[2]) && isfinite(y_est[0]) && isfinite(y_est[1]) && isfinite(y_est[2]))) {
|
||||
write_debug_log("BAD ESTIMATE AFTER CORRECTION", dt, x_est, y_est, z_est, x_est_prev, y_est_prev, z_est_prev, corr_acc, corr_gps, w_xy_gps_p, w_xy_gps_v);
|
||||
memcpy(x_est, x_est_prev, sizeof(x_est));
|
||||
memcpy(y_est, y_est_prev, sizeof(y_est));
|
||||
memset(corr_acc, 0, sizeof(corr_acc));
|
||||
memset(corr_gps, 0, sizeof(corr_gps));
|
||||
memset(corr_flow, 0, sizeof(corr_flow));
|
||||
|
||||
} else {
|
||||
memcpy(x_est_prev, x_est, sizeof(x_est));
|
||||
memcpy(y_est_prev, y_est, sizeof(y_est));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,7 +909,7 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
if (t > pub_last + pub_interval) {
|
||||
pub_last = t;
|
||||
/* publish local position */
|
||||
local_pos.xy_valid = can_estimate_xy && use_gps_xy;
|
||||
local_pos.xy_valid = can_estimate_xy;
|
||||
local_pos.v_xy_valid = can_estimate_xy;
|
||||
local_pos.xy_global = local_pos.xy_valid && use_gps_xy;
|
||||
local_pos.z_global = local_pos.z_valid && use_gps_z;
|
||||
@@ -831,40 +932,35 @@ int position_estimator_inav_thread_main(int argc, char *argv[])
|
||||
|
||||
orb_publish(ORB_ID(vehicle_local_position), vehicle_local_position_pub, &local_pos);
|
||||
|
||||
/* publish global position */
|
||||
global_pos.global_valid = local_pos.xy_global;
|
||||
if (local_pos.xy_global && local_pos.z_global) {
|
||||
/* publish global position */
|
||||
global_pos.timestamp = t;
|
||||
global_pos.time_gps_usec = gps.time_gps_usec;
|
||||
|
||||
if (local_pos.xy_global) {
|
||||
double est_lat, est_lon;
|
||||
map_projection_reproject(local_pos.x, local_pos.y, &est_lat, &est_lon);
|
||||
map_projection_reproject(&ref, local_pos.x, local_pos.y, &est_lat, &est_lon);
|
||||
|
||||
global_pos.lat = est_lat;
|
||||
global_pos.lon = est_lon;
|
||||
global_pos.time_gps_usec = gps.time_gps_usec;
|
||||
}
|
||||
global_pos.alt = local_pos.ref_alt - local_pos.z;
|
||||
|
||||
/* set valid values even if position is not valid */
|
||||
if (local_pos.v_xy_valid) {
|
||||
global_pos.vel_n = local_pos.vx;
|
||||
global_pos.vel_e = local_pos.vy;
|
||||
}
|
||||
|
||||
if (local_pos.z_global) {
|
||||
global_pos.alt = local_pos.ref_alt - local_pos.z;
|
||||
}
|
||||
|
||||
if (local_pos.z_valid) {
|
||||
global_pos.baro_alt = baro_offset - local_pos.z;
|
||||
}
|
||||
|
||||
if (local_pos.v_z_valid) {
|
||||
global_pos.vel_d = local_pos.vz;
|
||||
|
||||
global_pos.yaw = local_pos.yaw;
|
||||
|
||||
// TODO implement dead-reckoning
|
||||
global_pos.eph = gps.eph_m;
|
||||
global_pos.epv = gps.epv_m;
|
||||
|
||||
if (vehicle_global_position_pub < 0) {
|
||||
vehicle_global_position_pub = orb_advertise(ORB_ID(vehicle_global_position), &global_pos);
|
||||
|
||||
} else {
|
||||
orb_publish(ORB_ID(vehicle_global_position), vehicle_global_position_pub, &global_pos);
|
||||
}
|
||||
}
|
||||
|
||||
global_pos.yaw = local_pos.yaw;
|
||||
|
||||
global_pos.timestamp = t;
|
||||
|
||||
orb_publish(ORB_ID(vehicle_global_position), vehicle_global_position_pub, &global_pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ PARAM_DEFINE_FLOAT(INAV_W_XY_ACC, 20.0f);
|
||||
PARAM_DEFINE_FLOAT(INAV_W_XY_FLOW, 5.0f);
|
||||
PARAM_DEFINE_FLOAT(INAV_W_GPS_FLOW, 0.1f);
|
||||
PARAM_DEFINE_FLOAT(INAV_W_ACC_BIAS, 0.05f);
|
||||
PARAM_DEFINE_FLOAT(INAV_FLOW_K, 0.0165f);
|
||||
PARAM_DEFINE_FLOAT(INAV_FLOW_K, 0.15f);
|
||||
PARAM_DEFINE_FLOAT(INAV_FLOW_Q_MIN, 0.5f);
|
||||
PARAM_DEFINE_FLOAT(INAV_SONAR_FILT, 0.05f);
|
||||
PARAM_DEFINE_FLOAT(INAV_SONAR_ERR, 0.5f);
|
||||
|
||||
@@ -1102,8 +1102,8 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
log_msg.body.log_LPOS.vx = buf.local_pos.vx;
|
||||
log_msg.body.log_LPOS.vy = buf.local_pos.vy;
|
||||
log_msg.body.log_LPOS.vz = buf.local_pos.vz;
|
||||
log_msg.body.log_LPOS.ref_lat = buf.local_pos.ref_lat;
|
||||
log_msg.body.log_LPOS.ref_lon = buf.local_pos.ref_lon;
|
||||
log_msg.body.log_LPOS.ref_lat = buf.local_pos.ref_lat * 1e7;
|
||||
log_msg.body.log_LPOS.ref_lon = buf.local_pos.ref_lon * 1e7;
|
||||
log_msg.body.log_LPOS.ref_alt = buf.local_pos.ref_alt;
|
||||
log_msg.body.log_LPOS.xy_flags = (buf.local_pos.xy_valid ? 1 : 0) | (buf.local_pos.v_xy_valid ? 2 : 0) | (buf.local_pos.xy_global ? 8 : 0);
|
||||
log_msg.body.log_LPOS.z_flags = (buf.local_pos.z_valid ? 1 : 0) | (buf.local_pos.v_z_valid ? 2 : 0) | (buf.local_pos.z_global ? 8 : 0);
|
||||
@@ -1142,8 +1142,8 @@ int sdlog2_thread_main(int argc, char *argv[])
|
||||
log_msg.body.log_GPOS.vel_n = buf.global_pos.vel_n;
|
||||
log_msg.body.log_GPOS.vel_e = buf.global_pos.vel_e;
|
||||
log_msg.body.log_GPOS.vel_d = buf.global_pos.vel_d;
|
||||
log_msg.body.log_GPOS.baro_alt = buf.global_pos.baro_alt;
|
||||
log_msg.body.log_GPOS.flags = (buf.global_pos.baro_valid ? 1 : 0) | (buf.global_pos.global_valid ? 2 : 0);
|
||||
log_msg.body.log_GPOS.eph = buf.global_pos.eph;
|
||||
log_msg.body.log_GPOS.epv = buf.global_pos.epv;
|
||||
LOGBUFFER_WRITE_AND_COUNT(GPOS);
|
||||
}
|
||||
|
||||
|
||||
@@ -207,8 +207,8 @@ struct log_GPOS_s {
|
||||
float vel_n;
|
||||
float vel_e;
|
||||
float vel_d;
|
||||
float baro_alt;
|
||||
uint8_t flags;
|
||||
float eph;
|
||||
float epv;
|
||||
};
|
||||
|
||||
/* --- GPSP - GLOBAL POSITION SETPOINT --- */
|
||||
@@ -354,7 +354,7 @@ static const struct log_format_s log_formats[] = {
|
||||
LOG_FORMAT(AIRS, "fff", "IndSpeed,TrueSpeed,AirTemp"),
|
||||
LOG_FORMAT(ARSP, "fff", "RollRateSP,PitchRateSP,YawRateSP"),
|
||||
LOG_FORMAT(FLOW, "hhfffBB", "RawX,RawY,CompX,CompY,Dist,Q,SensID"),
|
||||
LOG_FORMAT(GPOS, "LLfffffB", "Lat,Lon,Alt,VelN,VelE,VelD,BaroAlt,Flags"),
|
||||
LOG_FORMAT(GPOS, "LLffffff", "Lat,Lon,Alt,VelN,VelE,VelD,EPH,EPV"),
|
||||
LOG_FORMAT(GPSP, "BLLffBfbf", "NavState,Lat,Lon,Alt,Yaw,Type,LoitR,LoitDir,PitMin"),
|
||||
LOG_FORMAT(ESC, "HBBBHHHHHHfH", "Counter,NumESC,Conn,N,Ver,Adr,Volt,Amp,RPM,Temp,SetP,SetPRAW"),
|
||||
LOG_FORMAT(GVSP, "fff", "VX,VY,VZ"),
|
||||
|
||||
@@ -57,6 +57,7 @@ struct optical_flow_s {
|
||||
|
||||
uint64_t timestamp; /**< in microseconds since system start */
|
||||
|
||||
uint64_t flow_timestamp; /**< timestamp from flow sensor */
|
||||
int16_t flow_raw_x; /**< flow in pixels in X direction, not rotation-compensated */
|
||||
int16_t flow_raw_y; /**< flow in pixels in Y direction, not rotation-compensated */
|
||||
float flow_comp_x_m; /**< speed over ground in meters, rotation-compensated */
|
||||
|
||||
@@ -63,9 +63,6 @@
|
||||
struct vehicle_global_position_s {
|
||||
uint64_t timestamp; /**< Time of this estimate, in microseconds since system start */
|
||||
|
||||
bool global_valid; /**< true if position satisfies validity criteria of estimator */
|
||||
bool baro_valid; /**< true if baro_alt is valid (vel_d is also valid in this case) */
|
||||
|
||||
uint64_t time_gps_usec; /**< GPS timestamp in microseconds */
|
||||
double lat; /**< Latitude in degrees */
|
||||
double lon; /**< Longitude in degrees */
|
||||
@@ -74,8 +71,8 @@ struct vehicle_global_position_s {
|
||||
float vel_e; /**< Ground east velocity, m/s */
|
||||
float vel_d; /**< Ground downside velocity, m/s */
|
||||
float yaw; /**< Yaw in radians -PI..+PI. */
|
||||
|
||||
float baro_alt; /**< Barometric altitude (not raw baro but fused with accelerometer) */
|
||||
float eph;
|
||||
float epv;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||
* Author: @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -35,6 +34,9 @@
|
||||
/**
|
||||
* @file vehicle_local_position.h
|
||||
* Definition of the local fused NED position uORB topic.
|
||||
*
|
||||
* @author Lorenz Meier <lm@inf.ethz.ch>
|
||||
* @author Anton Babushkin <anton.babushkin@me.com>
|
||||
*/
|
||||
|
||||
#ifndef TOPIC_VEHICLE_LOCAL_POSITION_H_
|
||||
@@ -72,8 +74,8 @@ struct vehicle_local_position_s {
|
||||
bool xy_global; /**< true if position (x, y) is valid and has valid global reference (ref_lat, ref_lon) */
|
||||
bool z_global; /**< true if z is valid and has valid global reference (ref_alt) */
|
||||
uint64_t ref_timestamp; /**< Time when reference position was set */
|
||||
int32_t ref_lat; /**< Reference point latitude in 1E7 degrees */
|
||||
int32_t ref_lon; /**< Reference point longitude in 1E7 degrees */
|
||||
double ref_lat; /**< Reference point latitude in degrees */
|
||||
double ref_lon; /**< Reference point longitude in degrees */
|
||||
float ref_alt; /**< Reference altitude AMSL in meters, MUST be set to current (not at reference point!) ground level */
|
||||
bool landed; /**< true if vehicle is landed */
|
||||
/* Distance to surface */
|
||||
|
||||
Reference in New Issue
Block a user