Skip to content

Commit 204c549

Browse files
authored
Refactor reference frame module (#135)
One last refactor for usability. This PR contains two primary changes, along with a scattering of clean ups and documentation re-writes. # Support for handling new reference frames Previously the `ReferenceFrame` enum contained a set list of known reference frames, and we made sure to maintain an internal list of transformations for that set list of reference frames. This approach is obviously pretty inflexible, so I've added a new variant to `ReferenceFrame` called `Other` to enable defining new reference frames at run-time. A `String` is used to represent the unknown reference frame types. This slots in easily with our use of the `strum` macros for converting the reference frame enums into or from strings, but this does make the `ReferenceFrame` type no longer triviably copy-able. I've attempted to reduce the number of clones of the new `ReferenceFrame`, but they can't be completely avoided without a significantly different approach of representing new reference frame types at run-time. I'd be happy to hear suggestions on alternative approaches if anyone has any. # Simplify managing reference frame transformations Previously it was expected that the user of the crate would get the list of hard-coded transformations with the `get_transformation` function. If you needed a single transformation that would suffice, but if we didn't have a direct transformation hard-coded for you then you'd need to perform multiple transformations. The `TransformationGraph` struct was available to help to figure out the shortest path of transformations from one reference frame to another, but the `TransformationGraph` object didn't actually handle the transformations for you. In short it was a bit of a pain to use the crate for simple transformations and a major pain to do more complicated transformations. To improve the situation I've replaced the old `TransformationGraph` type with a new `TransformationRepository` type which both maintains the graph of transformations and also applies multiple transformations for you in sequence when needed. You're able to easily get one pre-populated with the hard-coded transformations available, or an empty one, then add any additional transformations defined at run-time to the graph.
1 parent 0c6e051 commit 204c549

File tree

4 files changed

+685
-356
lines changed

4 files changed

+685
-356
lines changed

swiftnav/src/coords/mod.rs

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,7 @@ pub use ellipsoid::*;
8484
pub use llh::*;
8585
pub use ned::*;
8686

87-
use crate::{
88-
reference_frame::{get_transformation, ReferenceFrame, TransformationNotFound},
89-
time::GpsTime,
90-
};
87+
use crate::{reference_frame::ReferenceFrame, time::GpsTime};
9188
use nalgebra::Vector2;
9289

9390
/// WGS84 local horizontal coordinates consisting of an Azimuth and Elevation, with angles stored as radians
@@ -193,7 +190,7 @@ impl AsMut<Vector2<f64>> for AzimuthElevation {
193190
/// Complete coordinate used for transforming between reference frames
194191
///
195192
/// Velocities are optional, but when present they will be transformed
196-
#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)]
193+
#[derive(Debug, PartialEq, PartialOrd, Clone)]
197194
pub struct Coordinate {
198195
reference_frame: ReferenceFrame,
199196
position: ECEF,
@@ -218,7 +215,7 @@ impl Coordinate {
218215
}
219216
}
220217

221-
/// Create a new [`Coordinate`] object with a velocity value
218+
/// Create a new [`Coordinate`] object with no velocity value
222219
#[must_use]
223220
pub fn without_velocity(
224221
reference_frame: ReferenceFrame,
@@ -233,7 +230,7 @@ impl Coordinate {
233230
}
234231
}
235232

236-
/// Create a new [`Coordinate`] object with no velocity
233+
/// Create a new [`Coordinate`] object with a velocity
237234
#[must_use]
238235
pub fn with_velocity(
239236
reference_frame: ReferenceFrame,
@@ -251,8 +248,8 @@ impl Coordinate {
251248

252249
/// Get the reference frame of the coordinate
253250
#[must_use]
254-
pub fn reference_frame(&self) -> ReferenceFrame {
255-
self.reference_frame
251+
pub fn reference_frame(&self) -> &ReferenceFrame {
252+
&self.reference_frame
256253
}
257254

258255
/// Get the position of the coordinate
@@ -276,7 +273,7 @@ impl Coordinate {
276273
/// Use the velocity term to adjust the epoch of the coordinate.
277274
/// When a coordinate has no velocity the position won't be changed.
278275
#[must_use]
279-
pub fn adjust_epoch(&self, new_epoch: &GpsTime) -> Self {
276+
pub fn adjust_epoch(self, new_epoch: &GpsTime) -> Self {
280277
let dt =
281278
new_epoch.to_fractional_year_hardcoded() - self.epoch.to_fractional_year_hardcoded();
282279
let v = self.velocity.unwrap_or_default();
@@ -288,17 +285,6 @@ impl Coordinate {
288285
reference_frame: self.reference_frame,
289286
}
290287
}
291-
292-
/// Transform the coordinate from into a new reference frame
293-
///
294-
/// # Errors
295-
///
296-
/// An error is returned if a transformation from the coordinate's reference frame to the requested
297-
/// reference frame could not be found.
298-
pub fn transform_to(&self, new_frame: ReferenceFrame) -> Result<Self, TransformationNotFound> {
299-
get_transformation(self.reference_frame, new_frame)
300-
.map(|transformation| transformation.transform(self))
301-
}
302288
}
303289

304290
#[cfg(test)]
@@ -519,7 +505,7 @@ mod tests {
519505
initial_epoch,
520506
);
521507

522-
let new_coord = initial_coord.adjust_epoch(&new_epoch);
508+
let new_coord = initial_coord.clone().adjust_epoch(&new_epoch);
523509

524510
assert_eq!(initial_coord.reference_frame, new_coord.reference_frame);
525511
assert_float_eq!(new_coord.position.x(), 1.0, abs <= 0.001);

0 commit comments

Comments
 (0)