Skip to content

Commit

Permalink
feat: add StateBuilder (#237)
Browse files Browse the repository at this point in the history
* chore: rebase conflicts

* feat: add bindings (and fix typo bug

* chore: remove artifact from rebase

* feat: add functions to State and CoordinatesBroker to extract multiple subsets at once.

* feat: add bindings (and fix typo bug

* feat: initial commit to add StateBuilder hpp/cpp

* test: cleanup and add test file

* feat: add and test the rest of the boilerplate except for State generation function

* style: formatting

* feat: fully functional cpp code

* feat: add python bindings

* fix: several tests that started failing due to the new coordinates size constraint on State construction

* refactor: rename state method in python to build_state

* refactor: improve equality operator from MR comments
  • Loading branch information
kyle-cochran authored Oct 11, 2023
1 parent da64bba commit b12aadb
Show file tree
Hide file tree
Showing 12 changed files with 863 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <OpenSpaceToolkitAstrodynamicsPy/Trajectory/Segment.cpp>
#include <OpenSpaceToolkitAstrodynamicsPy/Trajectory/Sequence.cpp>
#include <OpenSpaceToolkitAstrodynamicsPy/Trajectory/State.cpp>
#include <OpenSpaceToolkitAstrodynamicsPy/Trajectory/StateBuilder.cpp>

inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory(pybind11::module& aModule)
{
Expand Down Expand Up @@ -56,6 +57,7 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory(pybind11::module& aModule
OpenSpaceToolkitAstrodynamicsPy_Trajectory_LocalOrbitalFrameDirection(trajectory);

OpenSpaceToolkitAstrodynamicsPy_Trajectory_State(trajectory);
OpenSpaceToolkitAstrodynamicsPy_Trajectory_StateBuilder(trajectory);
OpenSpaceToolkitAstrodynamicsPy_Trajectory_Orbit(trajectory);
OpenSpaceToolkitAstrodynamicsPy_Trajectory_Model(trajectory);
OpenSpaceToolkitAstrodynamicsPy_Trajectory_Propagator(trajectory);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/// Apache License 2.0

#include <OpenSpaceToolkit/Astrodynamics/Trajectory/StateBuilder.hpp>

inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory_StateBuilder(pybind11::module& aModule)
{
using namespace pybind11;

using ostk::core::types::Shared;
using ostk::core::ctnr::Array;

using ostk::physics::coord::Frame;

using ostk::astro::trajectory::State;
using ostk::astro::trajectory::StateBuilder;
using ostk::astro::trajectory::state::CoordinatesBroker;

class_<StateBuilder>(aModule, "StateBuilder")

.def(
init<const Shared<const Frame>&, const Array<Shared<const CoordinatesSubset>>&>(),
arg("frame"),
arg("coordinates_subsets")
)
.def(
init<const Shared<const Frame>&, const Shared<const CoordinatesBroker>&>(),
arg("frame"),
arg("coordinates_broker")
)

.def(self == self)
.def(self != self)

.def("__str__", &(shiftToString<StateBuilder>))
.def("__repr__", &(shiftToString<StateBuilder>))

.def("is_defined", &StateBuilder::isDefined)

.def("build_state", &StateBuilder::buildState)

.def("get_coordinates_subsets", &StateBuilder::getCoordinatesSubsets)
.def("get_frame", &StateBuilder::getFrame)

.def_static("undefined", &StateBuilder::Undefined)

;
}
21 changes: 16 additions & 5 deletions bindings/python/test/trajectory/test_propagator.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,18 @@ def environment(earth) -> Environment:


@pytest.fixture
def coordinates_broker():
def coordinates_broker_7d():
return CoordinatesBroker(
[
CartesianPosition.default(),
CartesianVelocity.default(),
CoordinatesSubset.mass(),
]
)


@pytest.fixture
def coordinates_broker_9d():
return CoordinatesBroker(
[
CartesianPosition.default(),
Expand All @@ -112,7 +123,7 @@ def coordinates_broker():

@pytest.fixture
def state(
satellite_system: SatelliteSystem, coordinates_broker: CoordinatesBroker
satellite_system: SatelliteSystem, coordinates_broker_7d: CoordinatesBroker
) -> State:
instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)

Expand All @@ -128,12 +139,12 @@ def state(
satellite_system.get_mass().in_kilograms() + propellant_mass,
]

return State(instant, coordinates, Frame.GCRF(), coordinates_broker)
return State(instant, coordinates, Frame.GCRF(), coordinates_broker_7d)


@pytest.fixture
def state_low_altitude(
satellite_system: SatelliteSystem, coordinates_broker: CoordinatesBroker
satellite_system: SatelliteSystem, coordinates_broker_9d: CoordinatesBroker
) -> State:
instant: Instant = Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)

Expand All @@ -153,7 +164,7 @@ def state_low_altitude(
cd,
]

return State(instant, coordinates, Frame.GCRF(), coordinates_broker)
return State(instant, coordinates, Frame.GCRF(), coordinates_broker_9d)


@pytest.fixture
Expand Down
99 changes: 99 additions & 0 deletions bindings/python/test/trajectory/test_state_builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Apache License 2.0

import pytest

import numpy as np

from ostk.physics.time import Instant
from ostk.physics.time import DateTime
from ostk.physics.time import Scale
from ostk.physics.coordinate import Frame

from ostk.astrodynamics.trajectory import (
State,
StateBuilder,
)
from ostk.astrodynamics.trajectory.state import (
CoordinatesBroker,
CoordinatesSubset,
)
from ostk.astrodynamics.trajectory.state.coordinates_subset import (
CartesianPosition,
CartesianVelocity,
)


@pytest.fixture()
def instant() -> Instant:
return Instant.date_time(DateTime(2018, 1, 1, 0, 0, 0), Scale.UTC)


@pytest.fixture
def frame() -> Frame:
return Frame.GCRF()


@pytest.fixture
def coordinates_subsets() -> list[CoordinatesSubset]:
return [CartesianPosition.default(), CartesianVelocity.default()]


@pytest.fixture
def coordinates_broker(coordinates_subsets: list[CoordinatesSubset]) -> CoordinatesBroker:
return CoordinatesBroker(coordinates_subsets)


@pytest.fixture
def state_builder(frame: Frame, coordinates_broker: CoordinatesBroker) -> State:
return StateBuilder(frame, coordinates_broker)


class TestState:
def test_broker_constructor(
self,
frame: Frame,
coordinates_broker: CoordinatesBroker,
):
builder = StateBuilder(frame, coordinates_broker)
assert builder is not None
assert isinstance(builder, StateBuilder)
assert builder.is_defined()

def test_subsets_constructor(
self,
frame: Frame,
coordinates_subsets: list[CoordinatesSubset],
):
builder = StateBuilder(frame, coordinates_subsets)
assert builder is not None
assert isinstance(builder, StateBuilder)
assert builder.is_defined()

def test_comparators(self, state_builder: StateBuilder):
assert (state_builder == state_builder) is True
assert (state_builder != state_builder) is False

def test_build_state(
self,
instant: Instant,
state_builder: StateBuilder,
):
coordinates = [1, 2, 3, 1, 2, 3]
state: State = state_builder.build_state(instant, coordinates)

assert state is not None
assert isinstance(state, State)
assert state.is_defined()
assert state.get_instant() == instant
assert (state.get_coordinates() == coordinates).all()
assert state.get_frame() == state_builder.get_frame()
assert state.get_coordinates_subsets() == state_builder.get_coordinates_subsets()

def test_getters(
self,
state_builder: StateBuilder,
frame: Frame,
coordinates_broker: CoordinatesBroker,
):
assert state_builder.get_frame() == frame
assert state_builder.get_coordinates_subsets() == coordinates_broker.get_subsets()
142 changes: 142 additions & 0 deletions include/OpenSpaceToolkit/Astrodynamics/Trajectory/StateBuilder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/// Apache License 2.0

#ifndef __OpenSpaceToolkit_Astrodynamics_Trajectory_StateBuilder__
#define __OpenSpaceToolkit_Astrodynamics_Trajectory_StateBuilder__

#include <OpenSpaceToolkit/Core/Containers/Array.hpp>
#include <OpenSpaceToolkit/Core/Types/Shared.hpp>

#include <OpenSpaceToolkit/Mathematics/Objects/Vector.hpp>

#include <OpenSpaceToolkit/Physics/Coordinate/Frame.hpp>
#include <OpenSpaceToolkit/Physics/Time/Instant.hpp>

#include <OpenSpaceToolkit/Astrodynamics/Trajectory/State.hpp>
#include <OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.hpp>
#include <OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesSubset.hpp>

namespace ostk
{
namespace astro
{
namespace trajectory
{

using ostk::core::types::Shared;
using ostk::core::ctnr::Array;

using ostk::math::obj::VectorXd;

using ostk::physics::coord::Frame;

using ostk::physics::time::Instant;

using ostk::astro::trajectory::State;
using ostk::astro::trajectory::state::CoordinatesBroker;
using ostk::astro::trajectory::state::CoordinatesSubset;

/// @brief Factory class to generate States with common reference frame and coordinates subsets

class StateBuilder
{
public:
/// @brief Constructor.
///
/// @param [in] aFrameSPtr The reference frame in which the coordinates are referenced to and
/// resolved in
/// @param [in] aCoordinatesSubsetsArray The array of coordinates subsets defining the output
/// States

StateBuilder(
const Shared<const Frame>& aFrameSPtr, const Array<Shared<const CoordinatesSubset>>& aCoordinatesSubsetsArray
);

/// @brief Constructor.
///
/// @param [in] aFrameSPtr The reference frame in which the coordinates are referenced to and
/// resolved in
/// @param [in] aCoordinatesBroker Shared pointer to an existing Coordinates Broker

StateBuilder(const Shared<const Frame>& aFrameSPtr, const Shared<const CoordinatesBroker>& aCoordinatesBrokerSPtr);

/// @brief Equality operator.
///
/// @param [in] aStateBuilder The StateBuilder to compare to
/// @return True if the StateBuilders are equal, false otherwise

bool operator==(const StateBuilder& aStateBuilder) const;

/// @brief Inequality operator.
///
/// @param [in] aStateBuilder The StateBuilder to compare to
/// @return True if the StateBuilders are not equal, false otherwise

bool operator!=(const StateBuilder& aStateBuilder) const;

/// @brief Stream insertion operator.
///
/// @param [in] anOutputStream The output stream to insert into
/// @param [in] aStateBuilder The StateBuilder to insert
/// @return The output stream with the StateBuilder inserted

friend std::ostream& operator<<(std::ostream& anOutputStream, const StateBuilder& aStateBuilder);

/// @brief Check if the StateBuilder is defined.
///
/// @return True if the StateBuilder is defined, false otherwise

bool isDefined() const;

/// @brief Produce a State linked to the Frame and Coordinates Broker of the StateBuilder.
///
/// @return A State linked to the Frame and Coordinates Broker of the StateBuilder

const State buildState(const Instant& anInstant, const VectorXd& aCoordinates) const;

/// @brief Accessor for the reference frame.
///
/// @return The reference frame

const Shared<const Frame> accessFrame() const;

/// @brief Access the coordinates broker associated with the StateBuilder.
///
/// @return The coordinates broker associated to the State

const Shared<const CoordinatesBroker>& accessCoordinatesBroker() const;

/// @brief Get the reference frame associated with the StateBuilder.
///
/// @return The reference frame

Shared<const Frame> getFrame() const;

/// @brief Get the coordinates subsets of the StateBuilder.
///
/// @return The coordinates subsets

const Array<Shared<const CoordinatesSubset>> getCoordinatesSubsets() const;

/// @brief Print the StateBuilder to an output stream.
///
/// @param [in] anOutputStream The output stream to print to
/// @param [in] displayDecorator Whether or not to display the decorator

void print(std::ostream& anOutputStream, bool displayDecorator = true) const;

/// @brief Get an undefined StateBuilder.
///
/// @return An undefined StateBuilder

static StateBuilder Undefined();

private:
Shared<const Frame> frameSPtr_;
Shared<const CoordinatesBroker> coordinatesBrokerSPtr_;
};

} // namespace trajectory
} // namespace astro
} // namespace ostk

#endif
6 changes: 4 additions & 2 deletions src/OpenSpaceToolkit/Astrodynamics/Trajectory/State.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/// Apache License 2.0

// #include <Eigen/Core>

#include <OpenSpaceToolkit/Core/Error.hpp>
#include <OpenSpaceToolkit/Core/Utilities.hpp>

Expand Down Expand Up @@ -34,6 +32,10 @@ State::State(
frameSPtr_(aFrameSPtr),
coordinatesBrokerSPtr_(aCoordinatesBrokerSPtr)
{
if (coordinatesBrokerSPtr_ && (Size)coordinates_.size() != coordinatesBrokerSPtr_->getNumberOfCoordinates())
{
throw ostk::core::error::runtime::Wrong("Number of Coordinates");
}
}

State::State(
Expand Down
Loading

0 comments on commit b12aadb

Please sign in to comment.