Skip to content
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

New Feature: Extended Kalman Filter State Estimator for SimpleFlight #4688

Open
wants to merge 95 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
3062a73
typedef EkfStates and EKfCovariance from Eigen lib
Nov 7, 2021
fece608
implement is_new flag for sensor models
Nov 7, 2021
cfc8a40
add creation of ekf unique pointer and passing a pointer into firmwar…
Nov 7, 2021
afba251
add ekf in Firmware constructor and call of ekf update
Nov 7, 2021
43a5526
implement interface to access sensor data from const board_, sensor m…
Nov 7, 2021
077352a
create four ekf hpp files and implement basic interfaces and function…
Nov 7, 2021
083161d
add parser and can run simpleflighttest
Nov 8, 2021
fd5d4c3
add quick and dirty commlink log of vehicle altitude series in Firmware
Nov 10, 2021
fda8c9d
update SimpleFlightTest.hpp
Nov 10, 2021
fda7312
fix ekf declaration
Nov 10, 2021
0a64ec7
fix board_ methods' polymorphism
Nov 10, 2021
b42e475
update gitignore to ignore log.txt
Nov 10, 2021
8b098bd
bug fix, memory leak due to wrong declaration of message
Nov 10, 2021
00c2754
merge airlibtest into ekf
Nov 10, 2021
ee84841
Sync environment with kinematics in physics engine ! only for standal…
Nov 12, 2021
dec9f8b
fix array out of bound in board
Nov 12, 2021
43c6945
change takeoff altituide for simple_flight
Nov 12, 2021
0da5d3d
transfer commlink log from Firmware to OffboardApi
Nov 12, 2021
1b304cd
make changes to ekf skeleton, log, and test: compiles and updates ekf…
Nov 12, 2021
54ae025
Merge branch 'microsoft:master' into ekf
subedisuman Nov 15, 2021
610de43
add ekf_ object as member of state_estimator_
Nov 16, 2021
dc097ca
change logging in OffBoardApi and log ekf position there
Nov 16, 2021
9d2fdd0
transport member object and get/setters from Base to IEkf
Nov 16, 2021
68afd59
implement evaluateStateDot function in ekf
Nov 16, 2021
62a25d7
implement statePropagation and initialization, remove logging in ekf
Nov 16, 2021
80093b8
running change in SimpleFlighttest.hpp, can run and log statePropagat…
Nov 16, 2021
1f2f45e
change and append Eigen matrix definitions
Nov 19, 2021
e547bda
change log in OffBoardApi.hpp
Nov 19, 2021
2af2270
add ekf position interface in flight estimator
Nov 19, 2021
9af2f54
add bash and python scripts to cleanup and plot log
Nov 19, 2021
4a536da
implement covariance propagration in EKF
Nov 19, 2021
1a7b7d8
Merge pull request #1 from rajat2004/use-geodetic-converter
subedisuman Dec 1, 2021
a99b08b
add geodetic2Ned interface for AirSim in GeodeticConverter
Dec 25, 2021
9de7f8e
add further matrix definitions in VectorMath
Dec 25, 2021
99ec240
add white noise model in gps sensor model
Dec 25, 2021
8313e59
change initialization order of ekf in Firmware
Dec 25, 2021
2ba0ca3
add setting of ground truth in ekf
Dec 25, 2021
e670538
add further interfaces in flight estimator to log and use ekf results
Dec 25, 2021
7b15666
add further ekf results data logging in OffboardApi
Dec 25, 2021
50eb767
add struct defintions for ekf
Dec 25, 2021
097227a
bulk changes in ekf model: implement measurement models and refactor …
Dec 25, 2021
6cf0769
bulk changes in ekf: implement measurement updates and filter intiali…
Dec 25, 2021
389ea38
add running changes in peripheral scripts
Dec 25, 2021
b01d624
add toggle for usage of true and estimated states
Jan 12, 2022
0267b1a
add EKF settings in AirSim settings
Jan 12, 2022
d7b031c
add further matrix definitions
Jan 12, 2022
4f21bf9
reset takeoff altitide to original value
Jan 12, 2022
65ae1c0
add simple_flight matrix definitions for EKF
Jan 12, 2022
3eb3bd8
block changes in AirSim EKF, ekf settings, cleanups...
Jan 12, 2022
46e89d4
running changes in other supplementary files
Jan 12, 2022
5914289
cosmetic cheanups
Jan 12, 2022
5981512
fixes
Jan 12, 2022
20dd1c1
fix euler angle covariance
Jan 17, 2022
25d7860
refactor ekf params
Jan 19, 2022
d4578b6
Merge branch 'master' of https://github.com/Microsoft/AirSim into ekf
Jan 19, 2022
3c1a072
cleanup
Jan 19, 2022
5d4a355
cleanup
Jan 19, 2022
1aa21f2
fix a typo in ekfparams
Jan 26, 2022
b40a3eb
update gitignore
Feb 14, 2022
44135b5
remove pure velocity zero condition before multirotor takeoff
Feb 14, 2022
0c8df51
running changes in peripherals for ekf
Feb 14, 2022
220337f
add runtime selection if ekf estimates are used via state estimator
Feb 15, 2022
76e46ac
cleanup simple_flight state estimator (cov -> var), implement public …
subedisuman Feb 16, 2022
0642df1
add settings params for gps noise
Feb 16, 2022
4ac246a
fix baro altitude in ekf, introduce bool for sensor fusion
Feb 16, 2022
8a8984d
fix virtual destructures warning
Feb 16, 2022
6c081f0
running change in simpleflighttest
Feb 16, 2022
6ce28d0
fix ekf settings not recognized by non-default vehicle
Feb 17, 2022
9c60cce
change ekf initial states setting to ekf initial state error
Feb 18, 2022
b9ba06a
change sensor bias model to negative
Feb 18, 2022
39fbca7
add turn on bias in imu from setting
Feb 18, 2022
60f563a
reset kinematics and environment before api in simpleflighttest
Feb 18, 2022
1410c7e
correct unit of gyro bias in ekf and imu model
Feb 18, 2022
78ac307
add quaternion normalization and lambda term in prediction step
Mar 23, 2022
2c95d02
delete codes not needed
Mar 23, 2022
f3633e7
cleanup more ekf code
Mar 23, 2022
b19f8d1
add euler angle covariance computation and getter
Mar 23, 2022
01f3c89
Merge branch 'master' of https://github.com/Microsoft/AirSim into ekf…
Mar 23, 2022
3b64859
cleanup ekf
Mar 23, 2022
69a5d24
merge origin/ekftest into ekf
Mar 23, 2022
5a3b26d
clang formating
Mar 23, 2022
aba2f16
fix double float conversion warning in sensors
Mar 23, 2022
b58a4ec
merge origin/ekftest into ekf
Mar 23, 2022
8d47e35
clang formating
Mar 23, 2022
84fc11b
fix further double to float warnings
Mar 23, 2022
a861f6a
fix further double to float warnings
Mar 23, 2022
dc008fe
fix further double to float warning
Mar 23, 2022
5654d19
clean airsimunittest
Mar 23, 2022
1ef34be
clean airsimunittest
Mar 23, 2022
15c64bf
fix further warning fixes
Mar 23, 2022
0a8ddc7
remove jacobian test
Mar 23, 2022
19a541c
add ekf data as line in RecordFileLine
Mar 25, 2022
a5e0e79
add vehicleresetapi
subedisuman Apr 4, 2022
2a27eb3
add python client scripts to run and plot ekf
subedisuman Apr 19, 2022
5b82314
fix the plot.py doc string
subedisuman Apr 19, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -397,5 +397,12 @@ build_docs/
# api docs
PythonClient/docs/_build

# Docker
/docker/Blocks/

# custom: ignore
/AirLibUnitTests/data
/AirLibUnitTests/figures
/AirLibUnitTests/log.txt
/AirLibUnitTests/data.csv
/AirLibUnitTests/figure*.pdf
/AirLibUnitTests/other.txt
build_AirSimEkfPod/
55 changes: 49 additions & 6 deletions AirLib/include/common/AirSimSettings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@ namespace airlib
float follow_distance = Utils::nan<float>();
};

struct EkfSetting
{
bool enabled = false;
Settings settings;
};

struct SensorSetting
{
SensorBase::SensorType sensor_type;
Expand Down Expand Up @@ -273,6 +279,7 @@ namespace airlib

std::map<std::string, CameraSetting> cameras;
std::map<std::string, std::shared_ptr<SensorSetting>> sensors;
std::shared_ptr<EkfSetting> ekf_setting;

RCSettings rc;

Expand Down Expand Up @@ -410,6 +417,9 @@ namespace airlib
float speed_unit_factor = 1.0f;
std::string speed_unit_label = "m\\s";
std::map<std::string, std::shared_ptr<SensorSetting>> sensor_defaults;

std::shared_ptr<EkfSetting> ekf_setting;

Vector3r wind = Vector3r::Zero();
std::map<std::string, CameraSetting> external_cameras;

Expand Down Expand Up @@ -446,7 +456,8 @@ namespace airlib
loadPawnPaths(settings_json, pawn_paths);
loadOtherSettings(settings_json);
loadDefaultSensorSettings(simmode_name, settings_json, sensor_defaults);
loadVehicleSettings(simmode_name, settings_json, vehicles, sensor_defaults);
loadEkfSettings(settings_json);
loadVehicleSettings(simmode_name, settings_json, vehicles, sensor_defaults, ekf_setting);
loadExternalCameraSettings(settings_json, external_cameras);

//this should be done last because it depends on vehicles (and/or their type) we have
Expand Down Expand Up @@ -801,7 +812,8 @@ namespace airlib

static std::unique_ptr<VehicleSetting> createVehicleSetting(const std::string& simmode_name, const Settings& settings_json,
const std::string vehicle_name,
std::map<std::string, std::shared_ptr<SensorSetting>>& sensor_defaults)
std::map<std::string, std::shared_ptr<SensorSetting>>& sensor_defaults,
std::shared_ptr<EkfSetting> ekf_setting)
{
auto vehicle_type = Utils::toLower(settings_json.getString("VehicleType", ""));

Expand Down Expand Up @@ -846,11 +858,15 @@ namespace airlib
loadCameraSettings(settings_json, vehicle_setting->cameras);
loadSensorSettings(settings_json, "Sensors", vehicle_setting->sensors, sensor_defaults);

// add ekf setting
vehicle_setting->ekf_setting = ekf_setting;

return vehicle_setting;
}

static void createDefaultVehicle(const std::string& simmode_name, std::map<std::string, std::unique_ptr<VehicleSetting>>& vehicles,
const std::map<std::string, std::shared_ptr<SensorSetting>>& sensor_defaults)
const std::map<std::string, std::shared_ptr<SensorSetting>>& sensor_defaults,
std::shared_ptr<EkfSetting> ekf_setting)
{
vehicles.clear();

Expand All @@ -864,6 +880,10 @@ namespace airlib
// currently keyboard is not supported so use rc as default
simple_flight_setting->rc.remote_control_id = 0;
simple_flight_setting->sensors = sensor_defaults;

// add ekf setting
simple_flight_setting->ekf_setting = ekf_setting;

vehicles[simple_flight_setting->vehicle_name] = std::move(simple_flight_setting);
}
else if (simmode_name == kSimModeTypeCar) {
Expand All @@ -887,9 +907,10 @@ namespace airlib

static void loadVehicleSettings(const std::string& simmode_name, const Settings& settings_json,
std::map<std::string, std::unique_ptr<VehicleSetting>>& vehicles,
std::map<std::string, std::shared_ptr<SensorSetting>>& sensor_defaults)
std::map<std::string, std::shared_ptr<SensorSetting>>& sensor_defaults,
std::shared_ptr<EkfSetting> ekf_setting)
{
createDefaultVehicle(simmode_name, vehicles, sensor_defaults);
createDefaultVehicle(simmode_name, vehicles, sensor_defaults, ekf_setting);

msr::airlib::Settings vehicles_child;
if (settings_json.getChild("Vehicles", vehicles_child)) {
Expand All @@ -903,7 +924,7 @@ namespace airlib
for (const auto& key : keys) {
msr::airlib::Settings child;
vehicles_child.getChild(key, child);
vehicles[key] = createVehicleSetting(simmode_name, child, key, sensor_defaults);
vehicles[key] = createVehicleSetting(simmode_name, child, key, sensor_defaults, ekf_setting);
}
}
}
Expand Down Expand Up @@ -1347,6 +1368,28 @@ namespace airlib
}
}

static std::shared_ptr<EkfSetting> createEkfSettings(bool enabled)
{
std::shared_ptr<EkfSetting> ekf_setting;

ekf_setting = std::shared_ptr<EkfSetting>(new EkfSetting());
ekf_setting->enabled = enabled;

return ekf_setting;
}

// creates and intializes Extended Kalman Filter (ekf) settings from json
void loadEkfSettings(const Settings& settings_json)
{
msr::airlib::Settings child;
if (settings_json.getChild("EkfSetting", child)) {
auto enabled = child.getBool("Enabled", false);
ekf_setting = createEkfSettings(enabled);
ekf_setting->enabled = enabled;
ekf_setting->settings = child;
}
}

// creates default sensor list when none specified in json
static void createDefaultSensorSettings(const std::string& simmode_name,
std::map<std::string, std::shared_ptr<SensorSetting>>& sensors)
Expand Down
46 changes: 46 additions & 0 deletions AirLib/include/common/EkfStructs.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

#ifndef msr_airlib_EkfStructs_hpp
#define msr_airlib_EkfStructs_hpp

#include "common/Common.hpp"

namespace msr
{
namespace airlib
{

struct SensorMeasurements
{
Vector3r accel;
Vector3r gyro;

Vector3r gps_position;
Vector3r gps_velocity;

real_T baro_altitude;

Vector3r magnetic_flux;
};

struct SensorBiases
{
Vector3r accel;
Vector3r gyro;

real_T barometer;
};

struct EkfKinematicsState
{
Vector3r position;
Quaternionr orientation;
Vector3r angles;

Vector3r linear_velocity;

SensorBiases sensor_bias;
};

}
} //namespace
#endif
19 changes: 11 additions & 8 deletions AirLib/include/common/GeodeticConverter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,8 @@ namespace airlib
geodetic2Ecef(home_latitude_, home_longitude_, home_altitude_, &home_ecef_x_, &home_ecef_y_, &home_ecef_z_);

// Compute ECEF to NED and NED to ECEF matrices
double phiP = atan2(home_ecef_z_, sqrt(pow(home_ecef_x_, 2) + pow(home_ecef_y_, 2)));

ecef_to_ned_matrix_ = nRe(phiP, home_longitude_rad_);
ned_to_ecef_matrix_ = nRe(home_latitude_rad_, home_longitude_rad_).transpose();
ecef_to_ned_matrix_ = nRe(home_latitude_rad_, home_longitude_rad_);
ned_to_ecef_matrix_ = ecef_to_ned_matrix_.inverse();
}

void setHome(const GeoPoint& home_geopoint)
Expand Down Expand Up @@ -136,17 +134,22 @@ namespace airlib
ecef2Ned(x, y, z, north, east, down);
}

void geodetic2Ned(const GeoPoint& geopoint, Vector3r& ned_pos)
{
double north, east, down;
geodetic2Ned(geopoint.latitude, geopoint.longitude, geopoint.altitude, &north, &east, &down);
ned_pos[0] = static_cast<float>(north);
ned_pos[1] = static_cast<float>(east);
ned_pos[2] = static_cast<float>(down);
}

void ned2Geodetic(const double north, const double east, const float down, double* latitude,
double* longitude, float* altitude)
{
// Local NED position to geodetic coordinates
double x, y, z;
ned2Ecef(north, east, down, &x, &y, &z);
ecef2Geodetic(x, y, z, latitude, longitude, altitude);

//TODO: above returns wrong altitude if down was positive. This is because sqrt return value would be -ve
//but normal sqrt only return +ve. For now we just override it.
*altitude = home_altitude_ - down;
}

void ned2Geodetic(const Vector3r& ned_pos, GeoPoint& geopoint)
Expand Down
28 changes: 28 additions & 0 deletions AirLib/include/common/VectorMath.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,34 @@ namespace airlib
typedef Eigen::Quaternion<double, Eigen::DontAlign> Quaterniond;
typedef Eigen::Matrix<double, 3, 3> Matrix3x3d;
typedef Eigen::Matrix<float, 3, 3> Matrix3x3f;

typedef Eigen::Matrix<float, 17, 1> Vector17f;
typedef Eigen::Matrix<float, 16, 1> Vector16f;
typedef Eigen::Matrix<float, 17, 17> Matrix17x17f;
typedef Eigen::Matrix<float, 17, 13> Matrix17x13f;
typedef Eigen::Matrix<float, 13, 13> Matrix13x13f;
typedef Eigen::Matrix<float, 1, 17> Matrix1x17f;
typedef Eigen::Matrix<float, 17, 1> Matrix17x1f;
typedef Eigen::Matrix<float, 3, 17> Matrix3x17f;
typedef Eigen::Matrix<float, 17, 3> Matrix17x3f;
typedef Eigen::Matrix<float, 6, 17> Matrix6x17f;
typedef Eigen::Matrix<float, 17, 6> Matrix17x6f;
typedef Eigen::Matrix<float, 13, 1> Vector13f;
typedef Eigen::Matrix<float, 7, 1> Vector7f;
typedef Eigen::Matrix<float, 6, 6> Matrix6x6f;
typedef Eigen::Matrix<float, 3, 4> Matrix3x4f;
typedef Eigen::Matrix<float, 4, 4> Matrix4x4f;

typedef Eigen::Matrix<float, 16, 16> Matrix16x16f;
typedef Eigen::Matrix<float, 16, 12> Matrix16x12f;
typedef Eigen::Matrix<float, 12, 12> Matrix12x12f;
typedef Eigen::Matrix<float, 1, 16> Matrix1x16f;
typedef Eigen::Matrix<float, 16, 1> Matrix16x1f;
typedef Eigen::Matrix<float, 3, 16> Matrix3x16f;
typedef Eigen::Matrix<float, 16, 3> Matrix16x3f;
typedef Eigen::Matrix<float, 6, 16> Matrix6x16f;
typedef Eigen::Matrix<float, 16, 6> Matrix16x6f;

typedef Eigen::AngleAxisd AngleAxisd;
typedef Eigen::AngleAxisf AngleAxisf;

Expand Down
11 changes: 7 additions & 4 deletions AirLib/include/physics/Environment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "common/UpdatableObject.hpp"
#include "common/CommonStructs.hpp"
#include "common/EarthUtils.hpp"
#include "common/GeodeticConverter.hpp"

namespace msr
{
Expand Down Expand Up @@ -53,12 +54,13 @@ namespace airlib

setHomeGeoPoint(initial_.geo_point);

updateState(initial_, home_geo_point_);
updateState(initial_);
}

void setHomeGeoPoint(const GeoPoint& home_geo_point)
{
home_geo_point_ = HomeGeoPoint(home_geo_point);
geodetic_converter_.setHome(home_geo_point);
}

GeoPoint getHomeGeoPoint() const
Expand Down Expand Up @@ -87,7 +89,7 @@ namespace airlib

virtual void update() override
{
updateState(current_, home_geo_point_);
updateState(current_);
}

protected:
Expand All @@ -106,9 +108,9 @@ namespace airlib
}

private:
static void updateState(State& state, const HomeGeoPoint& home_geo_point)
void updateState(State& state)
{
state.geo_point = EarthUtils::nedToGeodetic(state.position, home_geo_point);
geodetic_converter_.ned2Geodetic(state.position, state.geo_point);

real_T geo_pot = EarthUtils::getGeopotential(state.geo_point.altitude / 1000.0f);
state.temperature = EarthUtils::getStandardTemperature(geo_pot);
Expand All @@ -122,6 +124,7 @@ namespace airlib
private:
State initial_, current_;
HomeGeoPoint home_geo_point_;
GeodeticConverter geodetic_converter_;
};
}
} //namespace
Expand Down
13 changes: 13 additions & 0 deletions AirLib/include/sensors/SensorBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,16 @@ namespace airlib
ground_truth_.environment = environment;
}

virtual void update() override
{
is_new_ = false;
}

const bool& checkIfNew() const
{
return is_new_;
}

const GroundTruth& getGroundTruth() const
{
return ground_truth_;
Expand All @@ -68,6 +78,9 @@ namespace airlib
//ground truth can be shared between many sensors
GroundTruth ground_truth_ = { nullptr, nullptr };
std::string name_ = "";

protected:
bool is_new_ = false;
};
}
} //namespace
Expand Down
5 changes: 4 additions & 1 deletion AirLib/include/sensors/barometer/BarometerSimple.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ namespace airlib

delay_line_.update();

if (freq_limiter_.isWaitComplete())
if (freq_limiter_.isWaitComplete()) {
setOutput(delay_line_.getOutput());

is_new_ = true;
}
}
//*** End: UpdatableState implementation ***//

Expand Down
Loading