pub struct Orientation<In> { /* private fields */ }
Expand description
Defines the orientation of an object in CoordinateSystem
In
.
This includes yaw, pitch, and roll, so not just facing direction (which would miss roll).
Note that this type implements Deserialize
despite having unsafe
constructors – this is
because doing otherwise would be extremely unergonomic. However, when deserializing, the
coordinate system of the deserialized value is not checked, so this is a foot-gun to be
mindful of.
Implementations§
Source§impl<In> Orientation<In>
impl<In> Orientation<In>
Sourcepub fn from_tait_bryan_angles(
yaw: impl Into<Angle>,
pitch: impl Into<Angle>,
roll: impl Into<Angle>,
) -> Self
👎Deprecated: Prefer tait_bryan_builder
to avoid argument-order confusion
pub fn from_tait_bryan_angles( yaw: impl Into<Angle>, pitch: impl Into<Angle>, roll: impl Into<Angle>, ) -> Self
tait_bryan_builder
to avoid argument-order confusionConstructs an orientation from (intrinsic) yaw, pitch, and roll Tait-Bryan angles.
The meanings of yaw, pitch, and roll tend to align with common use in aerospace
applications (eg, FrdLike
or NedLike
), but are more formally defined as described
below.
Yaw is rotation about the Z axis of In
, with an object oriented at 0° yaw facing along
the positive X axis. Bearing::azimuth
tends to have the same semantics as yaw (but not
always; eg, this is not the case for ENU).
Since we are using intrinsic rotations (by convention), we now consider further rotations (ie, pitch and roll) to be with respect to the axes after applying the yaw. So, as an example, with a yaw of 90° in NED (ie, facing East), a pitch of 45° will tilt the nose of the plane up by 45° while still pointing the plane East.
Pitch is rotation about the Y axis, with an object at 0° pitch facing along the positive X
axis (again, this is the X axis with yaw applied). Bearing::elevation
tends to have the
same semantics as pitch (though again, watch out for ENU!).
Roll is rotation about the X axis, with an object with 0° roll having its positive body Z
axis pointing along positive Z. For instance, in NED, after applying a yaw of 90° and a
pitch of 45° (so the plane points directly East with its nose pitched up by 45°), applying
a roll of 20° would result in the plane’s nose still pointing in the same direction, but
rotated clockwise about its own axis by 20°. There is no equivalent to roll in Bearing
.
To determine the direction of rotation (ie, in which direction a positive angle goes), you
can use the right-hand rule for rotations: curl your fingers and stick your thumb
out in the positive direction of the axis you want to check rotation around (eg, positive Z
for yaw). The direction your fingers curl is the direction of (positive) rotation. Note
that a counterclockwise rotation about a Z if positive Z is down is a clockwise rotation
when viewed from negative Z (ie, “up”); this matches the common use of yaw in FrdLike
where a positive yaw means “to the right”, or in NedLike
where a positive yaw means
“eastward”.
Be aware that rotational angles have high ambiguities in literature and are easy to use wrong, especially because different fields tend to use the same term with different meanings (eg, “Euler angles” mean something else in aerospace than in mathematics).
Sourcepub fn aligned() -> Self
pub fn aligned() -> Self
Constructs an orientation that is aligned with the axes of the CoordinateSystem
In
.
That is equivalent to calling Orientation::from_tait_bryan_angles
with all
zero values.
Sourcepub fn tait_bryan_builder() -> TaitBryanBuilder<NeedsYaw, Orientation<In>>
pub fn tait_bryan_builder() -> TaitBryanBuilder<NeedsYaw, Orientation<In>>
Provides a type-safe builder for constructing an orientation from Tait-Bryan angles.
This builder enforces the correct intrinsic order (yaw → pitch → roll) at compile time and provides named parameters to prevent argument order confusion.
§Examples
use sguaba::{system, engineering::Orientation};
use uom::si::{f64::Angle, angle::degree};
system!(struct PlaneNed using NED);
let orientation = Orientation::<PlaneNed>::tait_bryan_builder()
.yaw(Angle::new::<degree>(90.0))
.pitch(Angle::new::<degree>(45.0))
.roll(Angle::new::<degree>(5.0))
.build();
The following examples should fail to compile because the angles are not provided in the correct order:
// Cannot call roll before pitch - roll() method doesn't exist on NeedsPitch state
let orientation = Orientation::<PlaneNed>::tait_bryan_builder()
.yaw(Angle::new::<degree>(90.0))
.roll(Angle::new::<degree>(5.0))
.pitch(Angle::new::<degree>(45.0))
.build();
// Cannot skip yaw and start with pitch - pitch() method doesn't exist on NeedsYaw state
let orientation = Orientation::<PlaneNed>::tait_bryan_builder()
.pitch(Angle::new::<degree>(45.0))
.yaw(Angle::new::<degree>(90.0))
.roll(Angle::new::<degree>(5.0))
.build();
Source§impl<In> Orientation<In>
impl<In> Orientation<In>
Sourcepub unsafe fn map_as_zero_in<To>(self) -> Rotation<In, To>
pub unsafe fn map_as_zero_in<To>(self) -> Rotation<In, To>
Constructs a rotation into CoordinateSystem
To
such that self
has an orientation of
zero in To
(ie, Orientation::aligned
).
Less informally, if this rotation is applied to this Orientation<In>
, it will yield
Orientation::aligned
as Orientation<To>
.
Conversely, if the inverse of this rotation is applied to Orientation::aligned
for
Orientation<To>
, it will yield this Orientation<In>
.
Or, alternatively phrased, this yields a transformation that
- takes a coordinate, vector, or orientation observed by the object with this orientation
in the coordinate system
In
; and - returns that coordinate or vector as if it were observed in a coordinate system (
To
) where thisOrientation<In>
isOrientation::aligned
.
Or, if you prefer a more mathematical description: this defines the pose of the whole
coordinate system To
in In
.
§Safety
This method allows you to end up with erroneous transforms if you’re not careful. See
Pose::map_as_zero_in
for more details.
Specifically in the case of Orientation
, you are also asserting that only rotation (ie,
no translation) is needed to convert from In
to To
.
§Examples
use approx::assert_relative_eq;
use sguaba::{system, Bearing, Coordinate, engineering::Orientation};
use uom::si::f64::{Angle, Length};
use uom::si::{angle::degree, length::meter};
system!(struct PlaneNed using NED);
system!(struct PlaneFrd using FRD);
// plane orientation in NED is yaw 90° (east), pitch 45° (climbing), roll 5° (tilted right)
let orientation = Orientation::<PlaneNed>::from_tait_bryan_angles(
Angle::new::<degree>(90.),
Angle::new::<degree>(45.),
Angle::new::<degree>(5.),
);
// plane observes something below it to its right (45° azimuth, -20° elevation),
// at a range of 100m.
let observation = Coordinate::<PlaneFrd>::from_bearing(
Bearing::builder()
.azimuth(Angle::new::<degree>(45.))
.elevation(Angle::new::<degree>(-20.)).expect("elevation is in-range")
.build(),
Length::new::<meter>(100.)
);
// to get the absolute bearing of the observation (ie, with respect to North and horizon),
// we can use map_as_zero_in to obtain a transformation from PlaneNed to PlaneFrd, and
// then invert it to go from PlaneFrd to PlaneNed:
let plane_frd_to_ned = unsafe { orientation.map_as_zero_in::<PlaneFrd>() }.inverse();
// applying that transform gives us the translated coordinate
let observation_in_ned = plane_frd_to_ned.transform(observation);
Sourcepub fn cast<NewIn>(self) -> Orientation<NewIn>where
In: EquivalentTo<NewIn>,
pub fn cast<NewIn>(self) -> Orientation<NewIn>where
In: EquivalentTo<NewIn>,
Casts the coordinate system type parameter of the orientation to the equivalent coordinate
system NewIn
.
See EquivalentTo
for details on when this is useful (and safe).
Note that this performs no transform on the orientation’s components, as that should be
unnecessary when EquivalentTo
is implemented.
use sguaba::{system, systems::EquivalentTo, Bearing, engineering::Orientation};
use uom::si::{f64::Angle, angle::degree};
system!(struct PlaneNedFromCrate1 using NED);
system!(struct PlaneNedFromCrate2 using NED);
// SAFETY: these are truly the same thing just defined in different places
unsafe impl EquivalentTo<PlaneNedFromCrate1> for PlaneNedFromCrate2 {}
unsafe impl EquivalentTo<PlaneNedFromCrate2> for PlaneNedFromCrate1 {}
let orientation_in_1 = Orientation::<PlaneNedFromCrate1>::from_tait_bryan_angles(
Angle::new::<degree>(90.),
Angle::new::<degree>(45.),
Angle::new::<degree>(5.),
);
assert_eq!(
Orientation::<PlaneNedFromCrate2>::from_tait_bryan_angles(
Angle::new::<degree>(90.),
Angle::new::<degree>(45.),
Angle::new::<degree>(5.),
),
orientation_in_1.cast::<PlaneNedFromCrate2>()
);
Sourcepub fn to_tait_bryan_angles(&self) -> (Angle, Angle, Angle)
pub fn to_tait_bryan_angles(&self) -> (Angle, Angle, Angle)
Returns the yaw-pitch-roll Tait-Bryan angles that describe this orientation.
See Orientation::from_tait_bryan_angles
for documentation about the exact meaning of
yaw, pitch, and roll here.
Trait Implementations§
Source§impl<In> Clone for Orientation<In>
impl<In> Clone for Orientation<In>
Source§impl<In: Debug> Debug for Orientation<In>
impl<In: Debug> Debug for Orientation<In>
Source§impl<In> Default for Orientation<In>
impl<In> Default for Orientation<In>
Source§impl<'de, In> Deserialize<'de> for Orientation<In>
impl<'de, In> Deserialize<'de> for Orientation<In>
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl<From, To> Mul<Orientation<To>> for RigidBodyTransform<From, To>
impl<From, To> Mul<Orientation<To>> for RigidBodyTransform<From, To>
Source§impl<From, To> Mul<Orientation<To>> for Rotation<From, To>
impl<From, To> Mul<Orientation<To>> for Rotation<From, To>
Source§type Output = Orientation<From>
type Output = Orientation<From>
*
operator.Source§impl<From, To> Mul<RigidBodyTransform<From, To>> for Orientation<From>
impl<From, To> Mul<RigidBodyTransform<From, To>> for Orientation<From>
Source§impl<From, To> Mul<Rotation<From, To>> for Orientation<From>
impl<From, To> Mul<Rotation<From, To>> for Orientation<From>
Source§impl<In> PartialEq for Orientation<In>
impl<In> PartialEq for Orientation<In>
Source§impl<In> Serialize for Orientation<In>
impl<In> Serialize for Orientation<In>
impl<In> Copy for Orientation<In>
Auto Trait Implementations§
impl<In> Freeze for Orientation<In>
impl<In> RefUnwindSafe for Orientation<In>where
In: RefUnwindSafe,
impl<In> Send for Orientation<In>where
In: Send,
impl<In> Sync for Orientation<In>where
In: Sync,
impl<In> Unpin for Orientation<In>where
In: Unpin,
impl<In> UnwindSafe for Orientation<In>where
In: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self
from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self
is actually part of its subset T
(and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset
but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self
to the equivalent element of its superset.