|
14 | 14 | //! Contained in this module is also a simple standard position measurement model for both |
15 | 15 | //! the UKF and particle filter. This model is used to update the state based on position |
16 | 16 | //! measurements in the local level frame (i.e. a GPS fix). |
17 | | -use crate::earth::{METERS_TO_DEGREES, relative_barometric_altitude}; |
| 17 | +use crate::earth::{expected_barometric_pressure, relative_barometric_altitude, METERS_TO_DEGREES}; |
18 | 18 | use crate::linalg::matrix_square_root; |
19 | 19 | use crate::{IMUData, StrapdownState, forward, wrap_to_2pi}; |
20 | 20 |
|
@@ -133,34 +133,89 @@ impl MeasurementModel for GPSVelocityMeasurement { |
133 | 133 | measurement_sigma_points |
134 | 134 | } |
135 | 135 | } |
136 | | -/// A releative barometric altitude measurement model that describes the relative altitude |
137 | | -/// based on a pressure measurement. This is typically used in barometric altimeters to |
138 | | -/// estimate the altitude relative to a reference pressure. |
| 136 | + |
| 137 | +/// GPS Position and Velocity measurement model |
| 138 | +#[derive(Clone, Debug, Default)] |
| 139 | +pub struct GPSPositionAndVelocityMeasurement { |
| 140 | + /// latitude in degrees |
| 141 | + pub latitude: f64, |
| 142 | + /// longitude in degrees |
| 143 | + pub longitude: f64, |
| 144 | + /// altitude in meters |
| 145 | + pub altitude: f64, |
| 146 | + /// Northward velocity in m/s |
| 147 | + pub northward_velocity: f64, |
| 148 | + /// Eastward velocity in m/s |
| 149 | + pub eastward_velocity: f64, |
| 150 | + /// Downward velocity in m/s |
| 151 | + // pub downward_velocity: f64, // GPS speed measurements do not typically provide vertical velocity |
| 152 | + /// noise standard deviation in meters for position |
| 153 | + pub horizontal_noise_std: f64, |
| 154 | + /// vertical noise standard deviation in meters for position |
| 155 | + pub vertical_noise_std: f64, |
| 156 | + /// noise standard deviation in m/s for velocity |
| 157 | + pub velocity_noise_std: f64, |
| 158 | +} |
| 159 | +impl MeasurementModel for GPSPositionAndVelocityMeasurement { |
| 160 | + fn get_dimension(&self) -> usize { |
| 161 | + 5 // latitude, longitude, altitude, northward velocity, eastward velocity |
| 162 | + } |
| 163 | + fn get_vector(&self) -> DVector<f64> { |
| 164 | + DVector::from_vec(vec![ |
| 165 | + self.latitude.to_radians(), |
| 166 | + self.longitude.to_radians(), |
| 167 | + self.altitude, |
| 168 | + self.northward_velocity, |
| 169 | + self.eastward_velocity, |
| 170 | + ]) |
| 171 | + } |
| 172 | + fn get_noise(&self) -> DMatrix<f64> { |
| 173 | + DMatrix::from_diagonal(&DVector::from_vec(vec![ |
| 174 | + (self.horizontal_noise_std * METERS_TO_DEGREES).powi(2), |
| 175 | + (self.horizontal_noise_std * METERS_TO_DEGREES).powi(2), |
| 176 | + self.vertical_noise_std.powi(2), |
| 177 | + self.velocity_noise_std.powi(2), |
| 178 | + self.velocity_noise_std.powi(2), |
| 179 | + ])) |
| 180 | + } |
| 181 | + fn get_sigma_points(&self, state_sigma_points: &DMatrix<f64>) -> DMatrix<f64> { |
| 182 | + let mut measurement_sigma_points = DMatrix::<f64>::zeros(5, state_sigma_points.ncols()); |
| 183 | + for (i, sigma_point) in state_sigma_points.column_iter().enumerate() { |
| 184 | + measurement_sigma_points[(0, i)] = sigma_point[0]; |
| 185 | + measurement_sigma_points[(1, i)] = sigma_point[1]; |
| 186 | + measurement_sigma_points[(2, i)] = sigma_point[2]; |
| 187 | + measurement_sigma_points[(3, i)] = sigma_point[3]; |
| 188 | + measurement_sigma_points[(4, i)] = sigma_point[4]; |
| 189 | + } |
| 190 | + measurement_sigma_points |
| 191 | + } |
| 192 | +} |
| 193 | + |
| 194 | +/// A releative relative altitude measurement derived from barometric pressure. |
| 195 | +/// Note that this measurement model is an altitude measurement derived from |
| 196 | +/// a barometric altimeter and not a direct calculation of altitude from the |
| 197 | +/// barometric pressure. |
139 | 198 | #[derive(Clone, Debug, Default)] |
140 | | -pub struct RelativeBarometricAltitudeMeasurement { |
141 | | - /// Measured pressure in Pa |
142 | | - pub pressure: f64, |
| 199 | +pub struct RelativeAltitudeMeasurement { |
| 200 | + /// Measured relative altitude in meters |
| 201 | + pub relative_altitude: f64, |
143 | 202 | /// Reference pressure in Pa |
144 | | - pub reference_pressure: f64, |
| 203 | + pub reference_altitude: f64, |
145 | 204 | } |
146 | | -impl MeasurementModel for RelativeBarometricAltitudeMeasurement { |
| 205 | +impl MeasurementModel for RelativeAltitudeMeasurement { |
147 | 206 | fn get_dimension(&self) -> usize { |
148 | 207 | 1 // relative altitude |
149 | 208 | } |
150 | 209 | fn get_vector(&self) -> DVector<f64> { |
151 | | - DVector::from_vec(vec![relative_barometric_altitude( |
152 | | - self.pressure, self.reference_pressure, |
153 | | - )]) |
| 210 | + DVector::from_vec(vec![self.relative_altitude + self.reference_altitude]) |
154 | 211 | } |
155 | 212 | fn get_noise(&self) -> DMatrix<f64> { |
156 | | - DMatrix::from_diagonal(&DVector::from_vec(vec![1e-3])) // 1 mm noise |
| 213 | + DMatrix::from_diagonal(&DVector::from_vec(vec![5.0])) // 1 mm noise |
157 | 214 | } |
158 | 215 | fn get_sigma_points(&self, state_sigma_points: &DMatrix<f64>) -> DMatrix<f64> { |
159 | | - let mut measurement_sigma_points = DMatrix::<f64>::zeros(1, state_sigma_points.ncols()); |
| 216 | + let mut measurement_sigma_points = DMatrix::<f64>::zeros(self.get_dimension(), state_sigma_points.ncols()); |
160 | 217 | for (i, sigma_point) in state_sigma_points.column_iter().enumerate() { |
161 | | - measurement_sigma_points[(0, i)] = relative_barometric_altitude( |
162 | | - sigma_point[2], self.reference_pressure, |
163 | | - ); |
| 218 | + measurement_sigma_points[(0, i)] = sigma_point[2]; |
164 | 219 | } |
165 | 220 | measurement_sigma_points |
166 | 221 | } |
|
0 commit comments