-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add topographic lift library and initial example implementation to SITL #28756
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -125,6 +125,13 @@ class AP_Terrain { | |||
*/ | ||||
bool height_amsl(const Location &loc, float &height, bool corrected = true); | ||||
|
||||
/* | ||||
find the terrain gradient (slope) for a location. | ||||
Gradient is [x, y] in m/m | ||||
|
||||
return false if not available | ||||
*/ | ||||
bool gradient(const Location &loc, Vector2f& gradient); | ||||
/* | ||||
find difference between home terrain height and the terrain | ||||
height at the current location in meters. A positive result | ||||
|
@@ -422,6 +429,7 @@ class AP_Terrain { | |||
|
||||
// cache the home altitude, as it is needed so often | ||||
float home_height; | ||||
Vector2f home_gradient; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
Location home_loc; | ||||
bool have_home_height; | ||||
|
||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#pragma once | ||
|
||
#include <AP_Common/Location.h> | ||
#include <AP_Math/vector3.h> | ||
|
||
|
||
// The front end for the AP_TopoLift library. | ||
class AP_TopoLift { | ||
public: | ||
|
||
// Get the terrain height of a point. | ||
virtual bool get_terrain_height(const Location loc, float& height_amsl) = 0; | ||
|
||
// // Calculate the wind rate of topographic influenced lift at the current location. | ||
virtual bool calc_lift(const Location loc, float& lift) = 0; | ||
|
||
// Get the wind estimate at the current location. | ||
virtual bool get_wind_at_current_loc(Vector3f& wind) = 0; | ||
|
||
// // Update state. | ||
// virtual void update() = 0; | ||
}; |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,90 @@ | ||||||||
#include "AP_TopoLiftSinglePointEstimate.h" | ||||||||
#include <AP_Terrain/AP_Terrain.h> | ||||||||
#include <AP_AHRS/AP_AHRS.h> | ||||||||
#include <AP_Math/vector2.h> | ||||||||
|
||||||||
|
||||||||
bool AP_TopoLiftSinglePointEstimate::get_terrain_height(const Location loc, float& height_amsl) { | ||||||||
|
||||||||
AP_Terrain *terrain = AP::terrain(); | ||||||||
if (terrain == nullptr) { | ||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
// status() handles enable check. | ||||||||
if (terrain->status() != AP_Terrain::TerrainStatusOK) { | ||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
const auto corrected = true; | ||||||||
return terrain->height_amsl(loc, height_amsl, corrected); | ||||||||
|
||||||||
|
||||||||
return true; | ||||||||
Comment on lines
+21
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
} | ||||||||
|
||||||||
bool AP_TopoLiftSinglePointEstimate::get_terrain_grad(const Location loc, Vector2f& grad) { | ||||||||
|
||||||||
AP_Terrain *terrain = AP::terrain(); | ||||||||
if (terrain == nullptr) { | ||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
// status() handles enable check. | ||||||||
if (terrain->status() != AP_Terrain::TerrainStatusOK) { | ||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
return terrain->gradient(loc, grad); | ||||||||
} | ||||||||
|
||||||||
bool AP_TopoLiftSinglePointEstimate::get_wind_at_current_loc(Vector3f& wind) { | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
etc |
||||||||
const AP_AHRS &ahrs = AP::ahrs(); | ||||||||
|
||||||||
return ahrs.wind_estimate(wind); | ||||||||
Comment on lines
+42
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we really be using I'm hoping to have a set of AHRS backend results available from the SITL backend which might allow for using the "perfect" AHRS for determining the simulatedwind and a stnadrd backend's results when using on a real vehicle. |
||||||||
} | ||||||||
|
||||||||
bool AP_TopoLiftSinglePointEstimate::calc_lift(const Location loc, float& lift, const Vector2f& env_wind) { | ||||||||
float terrain_height_amsl; | ||||||||
if (!get_terrain_height(loc, terrain_height_amsl)) { | ||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
[[maybe_unused]] const float veh_height_agl = loc.alt * 1E-2 - terrain_height_amsl; | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have a define for unused stuff |
||||||||
|
||||||||
Vector2f terrain_grad; | ||||||||
if (!get_terrain_grad(loc, terrain_grad)) { | ||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
lift = env_wind * terrain_grad; | ||||||||
|
||||||||
return true; | ||||||||
} | ||||||||
|
||||||||
bool AP_TopoLiftSinglePointEstimate::calc_lift(const Location loc, float& lift) { | ||||||||
float height_amsl; | ||||||||
if (!get_terrain_height(loc, height_amsl)) { | ||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
Vector3f wind; | ||||||||
if (!get_wind_at_current_loc(wind)) { | ||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
|
||||||||
Vector2f terrain_grad; | ||||||||
if (!get_terrain_grad(loc, terrain_grad)) { | ||||||||
return false; | ||||||||
} | ||||||||
|
||||||||
// TODO find a way to communicate steepness | ||||||||
[[maybe_unused]] auto const terrain_steepness = terrain_grad.length(); | ||||||||
|
||||||||
|
||||||||
// TODO compute lift based on gradient, wind, and altitude above terrain. | ||||||||
lift = 42.0; | ||||||||
|
||||||||
return true; | ||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
#pragma once | ||
|
||
#include "AP_TopoLift.h" | ||
|
||
// Implements a super basic topographic lift model that uses | ||
// the current UAV location, the local terrain gradient, | ||
// the current wind estimate, and current height above | ||
// terrain to calculate the theoretical amount of topographic lift. | ||
// This is not very realistic or accurate, but it is useful as a | ||
// demonstration of the AP_TopoLift library. | ||
// More comprehensive models may be developed, or run offboard | ||
// and supplied through AP_ExternalTopoLift. | ||
|
||
class AP_TopoLiftSinglePointEstimate : public AP_TopoLift { | ||
public: | ||
// Get the terrain height of a point. | ||
virtual bool get_terrain_height(const Location loc, float& height_amsl) override; | ||
|
||
// Calculate the wind rate of topographic influenced lift at the current location. | ||
virtual bool calc_lift(const Location loc, float& lift) override; | ||
|
||
// Calculate the wind rate of topographic influenced lift given the steady state environmental wind vector. | ||
virtual bool calc_lift(const Location loc, float& lift, const Vector2f& env_wind); | ||
|
||
// Get the wind estimate at the current location. | ||
virtual bool get_wind_at_current_loc(Vector3f& wind) override; | ||
|
||
bool get_terrain_grad(const Location loc, Vector2f& grad); | ||
|
||
// // Update state | ||
// virtual void update() override; | ||
}; |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,3 @@ | ||||||||||
#ifndef AP_TOPO_LIFT_ENABLED | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
#define AP_TOPO_LIFT_ENABLED 1 | ||||||||||
#endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# AP Topographic Lift | ||
|
||
This library is responsible for running model(s) that estimate the topographic lift. AP could support more advanced models, however only a simplistic model is supported today. | ||
|
||
## Interface | ||
|
||
* Current UAV location in global coordinates | ||
* Ability to query terrain elevation at lat-lon coordinates | ||
* Ability to retrieve the current wind estimate |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -853,7 +853,10 @@ void Aircraft::update_wind(const struct sitl_input &input) | |||||
sinf(radians(input.wind.direction))*cosf(radians(input.wind.dir_z)), | ||||||
sinf(radians(input.wind.dir_z))) * input.wind.speed; | ||||||
|
||||||
wind_ef.z += get_local_updraft(position + home.get_distance_NED_double(origin)); | ||||||
auto const curr_pos = position + home.get_distance_NED_double(origin); | ||||||
wind_ef.z += get_local_updraft(curr_pos); | ||||||
wind_ef.z += get_topo_lift(location); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely want this parameterized; don't want more CPU generally - even in SITL :-) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should I parameterize |
||||||
// wind_ef.z += get_topo_lift(location); | ||||||
|
||||||
const float wind_turb = input.wind.turbulence * 10.0f; // scale input.wind.turbulence to match standard deviation when using iir_coef=0.98 | ||||||
const float iir_coef = 0.98f; // filtering high frequencies from turbulence | ||||||
|
@@ -1244,6 +1247,29 @@ float Aircraft::get_local_updraft(const Vector3d ¤tPos) | |||||
return w; | ||||||
} | ||||||
|
||||||
|
||||||
float Aircraft::get_topo_lift(const Location &loc) | ||||||
{ | ||||||
const float speed = AP::sitl()->wind_speed; | ||||||
// A SITL wind of 0 is N wind (from N to S). | ||||||
// A SITL wind of 90 is E wind (from E to W). | ||||||
|
||||||
// This dir will be 0 with east wind. | ||||||
const float dir = radians(AP::sitl()->wind_direction - 90.0); | ||||||
|
||||||
// Wind in the topographic frame. X points east, Y points north. | ||||||
// East wind will be [speed, 0] | ||||||
// North wind will be [0, speed] | ||||||
const Vector2f wind_topo(cosf(dir) * speed, sinf(dir) * speed); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
// auto const wind_topo = Vector2f() | ||||||
float lift; | ||||||
if (topo_lift_estimate.calc_lift(loc, lift, wind_topo)) { | ||||||
return lift; | ||||||
} else { | ||||||
return 0.0; | ||||||
} | ||||||
} | ||||||
|
||||||
void Aircraft::add_twist_forces(Vector3f &rot_accel) | ||||||
{ | ||||||
if (sitl == nullptr) { | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const
these and define as part of declarationThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like the PR from yesterday:) #28734