R3::basic_orientation_qty
namespace nin::R3 {
template <std::floating_point T>
class basic_orientation_qty;
using orientation_qty = basic_orientation_qty<double>;
}
A 3D orientation quantity. It represents the angular state of a body in space. It is an abstract realisation of raw orientation coordinates with no relation to any coordinate system. The interface deliberately hides the underlying representation, exposing only the operations relevant to reasoning in terms of orientations. Spatial orientations can be contructed from and converted to a variety of representations.
Orientations are coordinates, not transformations. They have no
compose() or inv() functions.
To transform orientations and other objects, see
basic_rotations.
|
The type alias orientation_qty is provided for basic_orientation_qty<double>.
Member functions
(Constructor)
(Constructor)
|
(1) |
|
(2) |
|
(3) |
|
(4) |
|
(5) |
|
(6) |
|
(7) |
-
(1) Default constructor.
-
(2) Explicit converting constructor from a different floating-point precision.
-
(3) Constructs an orientation from a quaternion. If the norm is not unitary, it is normalised first. Throws
std::domain_errorif the quaternion is not finite or is zero. -
(4) Constructs an orientation from a 3×3 rotation matrix stored as a fixed-size 9-element container.
TMis any fixed-size container of 9 floating-point elements (e.g.std::array<T, 9>). Theorderparameter selects row-major or column-major layout; see matrix_ordering. Throws an exception if the matrix is singular, non-finite, or left-handed. -
(5) Constructs an orientation from two axes that define the body X and Y axes of the new frame.
TXandTYare any fixed-size containers of 3 floating-point elements (e.g.std::array<T, 3>) representing 3D vectors. If Y is not orthogonal to X, it is projected first onto the plane defined by vector X. Throws if X is zero or if Y is colinear with X. -
(6) Constructs an orientation from an axis-angle pair.
TAis any fixed-size container of 3 floating-point elements (e.g.std::array<T, 3>) representing the rotation axis. Throws if the axis is zero and the angle is non-zero simultaneously. -
(7) Constructs an orientation from three Euler angles using the intrinsic convention. See euler_seq for available sequences.
Constructors (6) and (7) are convenience forms equivalent to applying a rotation
to the default orientation: in (6), the rotation is the one specified
by the axis-angle pair; in (7), it is the composition of three elementary
rotations about the axes prescribed by euler_seq.
import ninbot;
#include <array>
int main() {
using namespace nin;
R3::orientation_qty identity;
R3::orientation_qty from_quat { quaternion{0.5, 0.5, 0.5, 0.5} };
R3::orientation_qty from_axisangle { std::array<double,3>{1,1,1}, 120_deg };
R3::orientation_qty from_euler { 180_deg, 0_deg, 1_rad, euler_seq::RollPitchYaw };
}
to_axis_angle
axis-angle representation
to_axis_angle
axis-angle representation
|
(1) |
Returns an object of type axis_angle that is defined as
struct axis_angle {
std::array<T,3> axis;
units::angle_v<T> angle;
};
This is a convenience convertor that returns the axis-angle pair of the
rotation that takes the default orientation to *this.
The value of angle lies in [0, π].
import ninbot;
using namespace nin;
int main() {
R3::orientation_qty ori { 0_deg, 0_deg, 270_deg, euler_seq::XYZ };
auto [axis, angle] = ori.to_axis_angle(); // axis = (0, 0, -1), angle = 90°
}
to_quaternion
quaternion representation
to_quaternion
quaternion representation
|
(1) |
Returns the representation of the orientation as a quaternion. The returned quaternion is not normalized.
import ninbot;
using namespace nin;
int main() {
R3::orientation_qty ori { quaternion{2, 2, 0, 0} };
double q_norm = norm(ori.to_quaternion()); // ≈ 0.707
quaternion unit_quaternion = ori.to_quaternion().normalize();
}
to_matrix
rotation-matrix representation
to_matrix
rotation-matrix representation
|
(1) |
Returns the orientation as nine elements laid out in the requested matrix ordering; see matrix_ordering for the possible values. The returned matrix is orthonormal and right-handed.
import ninbot;
using namespace nin;
int main() {
R3::orientation_qty o;
auto M = o.to_matrix(matrix_ordering::ROW_MAJOR); // identity matrix
}
to_euler_angles
Euler-angle representation
to_euler_angles
Euler-angle representation
|
(1) |
Returns the three Euler angles of the orientation.
See euler_seq for possible values of sequence.
This is a convenience convertor that decomposes the rotation that takes the
default orientation to *this into three elementary rotations about
the axes prescribed by sequence, in the intrinsic convention.
import ninbot;
using namespace nin;
int main() {
R3::orientation_qty o { 30_deg, 45_deg, 60_deg, euler_seq::XYZ };
std::array<units::angle, 3> ea = o.to_euler_angles(euler_seq::XYZ);
}
Non-member functions
slerp
spherical linear interpolation between orientations
slerp
spherical linear interpolation between orientations
|
(1) |
Interpolates between a and b along the unit quaternion sphere.
t is clamped to [0, 1].
Plain linear interpolation of orientation coordinates does not work:
blending quaternions, matrix entries or Euler angles componentwise
gives intermediates that are not valid orientations and that rotate
at an uneven rate. slerp instead sweeps the arc that joins a and
b directly, so every intermediate is a valid orientation and the
rotation advances at constant angular speed in t.
The optional length argument selects the shortest arc (default) or
the longest (reflex) arc around the back of the sphere,
and is of type slerp_solution defined as
enum struct slerp_solution {
SHORTEST, // Short-way interpolation (default)
REFLEX // Long-way (reflex arc) interpolation
};
import ninbot;
using namespace nin;
int main() {
R3::orientation_qty a;
R3::orientation_qty b { std::array<double,3>{1,1,1}, 120_deg };
R3::orientation_qty halfway = slerp(a, b, 0.25); // 30° around (1,1,1)/√3
}
std::formatter<>
STL overload for the std::format and std::print families.
std::formatter<>
STL overload for the std::format and std::print families.
|
(1) |
Adds a specialization of std::formatter
that formats the orientation in one of three representations:
axis-angle (default), Euler angles, or quaternion.
The <format-spec> syntax is
[<float-spec>] [ ":" <repr> [<euler-order>] [ "|" <sep1> [ "|" <sep2> ] ] ]
with the following rules:
-
<float-spec>— anything before the first:or|is forwarded verbatim to the STL formatter for floating points and applied to every numeric value. -
<repr>— representation specifier:-
e— Euler angles in radians -
E— Euler angles in degrees -
q— Quaternion -
x— Axis-angle in radians — default -
X— Axis-angle in degrees
-
-
<euler-order>— only valid aftere/E. Three uppercase letters selecting the Euler convention, following the intrinsic convention. Accepted values:-
Tait–Bryan:
XYZ(default),XZY,YXZ,YZX,ZXY,ZYX. -
Proper Euler:
XYX,YXY,XZX,ZXZ,YZY,ZYZ. -
Aliases:
RPY(=XYZ, roll-pitch-yaw) andYPR(=ZYX).
-
-
Parentheses and separators — when no
|appears in the spec, the output is wrapped in parentheses and uses the default separators shown in the examples below. The presence of any|drops the surrounding parentheses; the text after|(and after the optional second|) overrides the defaults. A literal|inside a separator must be escaped as\|. The meaning of<sep1>and<sep2>depends on<repr>:-
x/X— default form(ax, ay, az; angle). With one separator|s, both the within-axis separator and the axis/angle separator becomes. With two separators|s1|s2,s1becomes the within-axis separator ands2becomes the axis/angle separator. -
q— default form(w; x, y, z). With one separator|s, both the scalar/vector separator and the within-vector separator becomes. With two separators|s1|s2,s1becomes the scalar/vector separator ands2becomes the within-vector separator. -
e/E— default form(α, β, γ). Only<sep1>is meaningful and replaces the separator between the three Euler components; a second|is not used.
-
import ninbot;
#include <print>
int main() {
nin::R3::orientation_qty rz90 { std::array<double,3>{0, 0, 1}, 90_deg };
nin::R3::orientation_qty identity;
std::println("{}", identity); // "(1, 0, 0; 0 rad)"
std::println("{:.1f}", rz90); // "(0.0, 0.0, 1.0; 1.6 rad)"
std::println("{:.1f:X}", rz90); // "(0.0, 0.0, 1.0; 90.0°)"
std::println("{:.2f:x|, | -- }", rz90); // "0.00, 0.00, 1.00 -- 1.57 rad"
std::println("{::q}", identity); // "(1; 0, 0, 0)"
std::println("{:.2f:q|, }", rz90); // "0.71, 0.00, 0.00, 0.71"
std::println("{::q|; |, }", identity); // "1; 0, 0, 0"
std::println("{:.1f:E}", rz90); // "(0.0°, 0.0°, 90.0°)"
std::println("{:.1f:EXYZ}", rz90); // "(0.0°, 0.0°, 90.0°)"
std::println("{:.1f:EXYZ|; }", rz90); // "0.0°; 0.0°; 90.0°"
std::println("{:.6f:eXYZ}", rz90); // "(0.000000, 0.000000, 1.570796) (rad)"
std::println("{:.1f:EYPR}", rz90); // "(90.0°, 0.0°, -0.0°)"
}
Non-member types
euler_seq
Euler-angle axis-sequence selector (intrinsic convention).
euler_seq
Euler-angle axis-sequence selector (intrinsic convention).
Selects the intrinsic rotation sequence used when dealing with Euler angles.
enum struct nin::euler_seq {
XYX, YXY, XZX, ZXZ, YZY, ZYZ, // Proper Euler angles
XYZ, XZY, YXZ, YZX, ZXY, ZYX, // Tait-Bryan angles
RollPitchYaw // Same as XYZ
};
The three letters of each sequence label name the body axes that the
three angles (first, second, third) refer to — first is the angle
about the body axis denoted by the first letter, second about the
second letter, third about the third letter. The body rotations
are applied in the reverse of that order, from the last letter to
the first.
For example, euler_seq::XYZ (equivalently RollPitchYaw) with the
tuple (roll, pitch, yaw):
-
rotate the body about its Z axis by
yaw, -
then about the new Y' axis by
pitch, -
then about the new X'' axis by
roll.
Equivalently, viewed as rotations about the fixed world axes, the same orientation is obtained by:
-
rotating about the world X axis by
roll, -
then about the world Y axis by
pitch, -
then about the world Z axis by
yaw.
This matches the standard aerospace yaw–pitch–roll convention where yaw is the rotation applied first to the body.
The same scheme applies to every sequence. For instance,
euler_seq::ZYX with angles (α, β, γ) rotates the body first about
its X axis by γ, then about the new Y' axis by β, then about the
new Z'' axis by α.
matrix_ordering
Memory layout selector for matrices.
matrix_ordering
Memory layout selector for matrices.
enum nin::matrix_ordering {
COLUMN_MAJOR,
ROW_MAJOR,
};
Selects how a matrix is laid out as a flat array.
|
(R00, R01, R02, …, R10, R11, R12, …) |
|
(R00, R10, R20, …, R01, R11, R21, …) |
- Row-major libraries
-
Blaze (default), Boost.MultiArray, Boost.uBLAS (default), C/C++ multidimensional arrays, GSL, NumPy (pybind11 / NumPy C API, default C order), OpenCV, ROS (tf2::Matrix3x3),
std::mdspanwithlayout_right - Column-major libraries
-
Armadillo, Ceres, DirectX/HLSL (default), Eigen (default), Fortran, GLSL, MATLAB/mex arrays, OpenGL, R (Rcpp / R C API),
std::mdspanwithlayout_left