Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d5240c1d30d8
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: ca0c5c99da58
Choose a head ref
  • 3 commits
  • 11 files changed
  • 1 contributor

Commits on Oct 26, 2019

  1. Changes for inertia tensor.

    pleroy committed Oct 26, 2019
    Copy the full SHA
    5725bed View commit details
  2. Lint and tolerance.

    pleroy committed Oct 26, 2019
    Copy the full SHA
    8746eb6 View commit details
  3. Merge pull request #2364 from pleroy/Geometry

    Changes to geometry to support the inertia tensor
    pleroy authored Oct 26, 2019

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ca0c5c9 View commit details
7 changes: 7 additions & 0 deletions geometry/identity.hpp
Original file line number Diff line number Diff line change
@@ -14,6 +14,9 @@ namespace geometry {
FORWARD_DECLARE_FROM(orthogonal_map,
TEMPLATE(typename FromFrame, typename ToFrame) class,
OrthogonalMap);
FORWARD_DECLARE_FROM(symmetric_bilinear_form,
TEMPLATE(typename Scalar, typename Frame) class,
SymmetricBilinearForm);

namespace internal_identity {

@@ -41,6 +44,10 @@ class Identity : public LinearMap<FromFrame, ToFrame> {
Trivector<Scalar, ToFrame> operator()(
Trivector<Scalar, FromFrame> const& trivector) const;

template<typename Scalar>
SymmetricBilinearForm<Scalar, ToFrame> operator()(
SymmetricBilinearForm<Scalar, FromFrame> const& form) const;

template<typename T>
typename base::Mappable<Identity, T>::type operator()(T const& t) const;

7 changes: 7 additions & 0 deletions geometry/identity_body.hpp
Original file line number Diff line number Diff line change
@@ -45,6 +45,13 @@ Trivector<Scalar, ToFrame> Identity<FromFrame, ToFrame>::operator()(
return Trivector<Scalar, ToFrame>(trivector.coordinates());
}

template<typename FromFrame, typename ToFrame>
template<typename Scalar>
SymmetricBilinearForm<Scalar, ToFrame> Identity<FromFrame, ToFrame>::operator()(
SymmetricBilinearForm<Scalar, FromFrame> const& form) const {
return SymmetricBilinearForm<Scalar, ToFrame>(form.coordinates());
}

template<typename FromFrame, typename ToFrame>
template<typename T>
typename base::Mappable<Identity<FromFrame, ToFrame>, T>::type
49 changes: 31 additions & 18 deletions geometry/identity_test.cpp
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
#include "geometry/frame.hpp"
#include "geometry/orthogonal_map.hpp"
#include "geometry/r3_element.hpp"
#include "geometry/symmetric_bilinear_form.hpp"
#include "glog/logging.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -29,19 +30,23 @@ class IdentityTest : public testing::Test {
serialization::Frame::TEST2, true>;
using Orth = OrthogonalMap<World1, World2>;
using Id = Identity<World1, World2>;
using R3 = R3Element<quantities::Length>;

IdentityTest() {
vector_ = Vector<quantities::Length, World1>(
R3(1.0 * Metre, 2.0 * Metre, 3.0 * Metre));
bivector_ = Bivector<quantities::Length, World1>(
R3(1.0 * Metre, 2.0 * Metre, 3.0 * Metre));
trivector_ = Trivector<quantities::Length, World1>(4.0 * Metre);
}

Vector<quantities::Length, World1> vector_;
Bivector<quantities::Length, World1> bivector_;
Trivector<quantities::Length, World1> trivector_;
using R3 = R3Element<Length>;

IdentityTest()
: vector_(Vector<Length, World1>(
R3(1.0 * Metre, 2.0 * Metre, 3.0 * Metre))),
bivector_(Bivector<Length, World1>(
R3(1.0 * Metre, 2.0 * Metre, 3.0 * Metre))),
trivector_(Trivector<Length, World1>(4.0 * Metre)),
form_(SymmetricBilinearForm<Length, World1>(
R3x3Matrix<Length>({1.0 * Metre, 2.0 * Metre, 3.0 * Metre},
{2.0 * Metre, 5.0 * Metre, 6.0 * Metre},
{3.0 * Metre, 6.0 * Metre, 4.0 * Metre}))) {}

Vector<Length, World1> const vector_;
Bivector<Length, World1> const bivector_;
Trivector<Length, World1> const trivector_;
SymmetricBilinearForm<Length, World1> const form_;
};

using IdentityDeathTest = IdentityTest;
@@ -65,11 +70,19 @@ TEST_F(IdentityTest, AppliedToTrivector) {
Eq(4.0 * Metre));
}

TEST_F(IdentityTest, AppliedToSymmetricBilinearForm) {
R3x3Matrix<Length> const expected_coordinates(
{1.0 * Metre, 2.0 * Metre, 3.0 * Metre},
{2.0 * Metre, 5.0 * Metre, 6.0 * Metre},
{3.0 * Metre, 6.0 * Metre, 4.0 * Metre});
EXPECT_THAT(Id()(form_).coordinates(),
Eq(expected_coordinates));
}

TEST_F(IdentityTest, Inverse) {
Vector<quantities::Length, World1> const vector1 = vector_;
Vector<quantities::Length, World2> const vector2 =
Vector<quantities::Length, World2>(
R3(1.0 * Metre, 2.0 * Metre, 3.0 * Metre));
Vector<Length, World1> const vector1 = vector_;
Vector<Length, World2> const vector2 =
Vector<Length, World2>(R3(1.0 * Metre, 2.0 * Metre, 3.0 * Metre));
EXPECT_THAT(Id().Inverse()(vector2).coordinates(),
Eq<R3>({1.0 * Metre, 2.0 * Metre, 3.0 * Metre}));
Id id;
@@ -99,7 +112,7 @@ TEST_F(IdentityTest, Compose) {
Id13 const id13 = id23 * id12;
Orth13 const o13 = o23 * o12;
for (Length l = 1 * Metre; l < 4 * Metre; l += 1 * Metre) {
Vector<quantities::Length, World1> modified_vector(
Vector<Length, World1> modified_vector(
{l, vector_.coordinates().y, vector_.coordinates().z});
EXPECT_THAT(id13(modified_vector), Eq(o13(modified_vector)));
}
4 changes: 4 additions & 0 deletions geometry/linear_map.hpp
Original file line number Diff line number Diff line change
@@ -38,6 +38,10 @@ class LinearMap {
// virtual Trivector<Scalar, ToFrame> operator()(
// Trivector<Scalar, FromFrame> const& trivector) const = 0;
//
// template<typename Scalar>
// SymmetricBilinearForm<Scalar, ToFrame> operator()(
// SymmetricBilinearForm<Scalar, FromFrame> const& form) const = 0;
//
// template<typename T>
// typename base::Mappable<LinearMap, T>::type operator()(T const& t) const;
//
4 changes: 4 additions & 0 deletions geometry/r3x3_matrix.hpp
Original file line number Diff line number Diff line change
@@ -37,6 +37,10 @@ class R3x3Matrix final {
Cube<Scalar> Determinant() const;
R3x3Matrix Transpose() const;

R3Element<Scalar> const& row_x() const;
R3Element<Scalar> const& row_y() const;
R3Element<Scalar> const& row_z() const;

Scalar operator()(int r, int c) const;

R3x3Matrix& operator+=(R3x3Matrix const& right);
29 changes: 22 additions & 7 deletions geometry/r3x3_matrix_body.hpp
Original file line number Diff line number Diff line change
@@ -38,6 +38,28 @@ Cube<Scalar> R3x3Matrix<Scalar>::Determinant() const {
row_x_.x * row_y_.z * row_z_.y;
}

template<typename Scalar>
R3x3Matrix<Scalar> R3x3Matrix<Scalar>::Transpose() const {
return R3x3Matrix({row_x_.x, row_y_.x, row_z_.x},
{row_x_.y, row_y_.y, row_z_.y},
{row_x_.z, row_y_.z, row_z_.z});
}

template<typename Scalar>
R3Element<Scalar> const& R3x3Matrix<Scalar>::row_x() const {
return row_x_;
}

template<typename Scalar>
R3Element<Scalar> const& R3x3Matrix<Scalar>::row_y() const {
return row_y_;
}

template<typename Scalar>
R3Element<Scalar> const& R3x3Matrix<Scalar>::row_z() const {
return row_z_;
}

template<typename Scalar>
FORCE_INLINE(inline) Scalar R3x3Matrix<Scalar>::operator()(
int const r, int const c) const {
@@ -55,13 +77,6 @@ FORCE_INLINE(inline) Scalar R3x3Matrix<Scalar>::operator()(
}
}

template<typename Scalar>
R3x3Matrix<Scalar> R3x3Matrix<Scalar>::Transpose() const {
return R3x3Matrix({row_x_.x, row_y_.x, row_z_.x},
{row_x_.y, row_y_.y, row_z_.y},
{row_x_.z, row_y_.z, row_z_.z});
}

template<typename Scalar>
R3x3Matrix<Scalar>& R3x3Matrix<Scalar>::operator+=(
R3x3Matrix const& right) {
8 changes: 8 additions & 0 deletions geometry/rotation.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

#pragma once

#include "base/macros.hpp"
#include "base/mappable.hpp"
#include "geometry/grassmann.hpp"
#include "geometry/linear_map.hpp"
@@ -16,6 +17,9 @@ namespace geometry {
FORWARD_DECLARE_FROM(orthogonal_map,
TEMPLATE(typename FromFrame, typename ToFrame) class,
OrthogonalMap);
FORWARD_DECLARE_FROM(symmetric_bilinear_form,
TEMPLATE(typename Scalar, typename Frame) class,
SymmetricBilinearForm);

namespace internal_rotation {

@@ -209,6 +213,10 @@ class Rotation : public LinearMap<FromFrame, ToFrame> {
Trivector<Scalar, ToFrame> operator()(
Trivector<Scalar, FromFrame> const& trivector) const;

template<typename Scalar>
SymmetricBilinearForm<Scalar, ToFrame> operator()(
SymmetricBilinearForm<Scalar, FromFrame> const& form) const;

template<typename T>
typename base::Mappable<Rotation, T>::type operator()(T const& t) const;

48 changes: 48 additions & 0 deletions geometry/rotation_body.hpp
Original file line number Diff line number Diff line change
@@ -208,6 +208,54 @@ Trivector<Scalar, ToFrame> Rotation<FromFrame, ToFrame>::operator()(
return trivector;
}

template<typename FromFrame, typename ToFrame>
template<typename Scalar>
SymmetricBilinearForm<Scalar, ToFrame> Rotation<FromFrame, ToFrame>::operator()(
SymmetricBilinearForm<Scalar, FromFrame> const& form) const {
// If R is the rotation and F the form, we compute R * F * R⁻¹. Note however
// that we only have mechanisms for applying rotations to column vectors. If
// r is a row of F, we first compute the corresponding row of the intermediate
// matrix F * R⁻¹ as R * ᵗr. We then transpose the intermediate matrix and
// multiply each column by R.
R3x3Matrix<Scalar> const& form_coordinates = form.coordinates();

// The matrix is symmetric, so what you call rows I call columns.
Vector<Scalar, FromFrame> const column_x(form_coordinates.row_x());
Vector<Scalar, FromFrame> const column_y(form_coordinates.row_y());
Vector<Scalar, FromFrame> const column_z(form_coordinates.row_z());

Vector<Scalar, ToFrame> const intermediate_row_x = (*this)(column_x);
Vector<Scalar, ToFrame> const intermediate_row_y = (*this)(column_y);
Vector<Scalar, ToFrame> const intermediate_row_z = (*this)(column_z);

R3x3Matrix<Scalar> intermediate_matrix(intermediate_row_x.coordinates(),
intermediate_row_y.coordinates(),
intermediate_row_z.coordinates());
intermediate_matrix = intermediate_matrix.Transpose();

// Note that transposing here effectively changes frames.
Vector<Scalar, FromFrame> const intermediate_column_x(
intermediate_matrix.row_x());
Vector<Scalar, FromFrame> const intermediate_column_y(
intermediate_matrix.row_y());
Vector<Scalar, FromFrame> const intermediate_column_z(
intermediate_matrix.row_z());

Vector<Scalar, ToFrame> const result_row_x = (*this)(intermediate_column_x);
Vector<Scalar, ToFrame> const result_row_y = (*this)(intermediate_column_y);
Vector<Scalar, ToFrame> const result_row_z = (*this)(intermediate_column_z);

R3x3Matrix<Scalar> const result_matrix(result_row_x.coordinates(),
result_row_y.coordinates(),
result_row_z.coordinates());

// The averaging below ensures that the result is symmetric.
// TODO(phl): Investigate if using a Cholesky or LDL decomposition would help
// preserve symmetry and/or definiteness.
return SymmetricBilinearForm<Scalar, ToFrame>(
0.5 * (result_matrix + result_matrix.Transpose()));
}

template<typename FromFrame, typename ToFrame>
template<typename T>
typename base::Mappable<Rotation<FromFrame, ToFrame>, T>::type
Loading