Skip to content

Commit

Permalink
feat: add dynamics contribution getters to segment solution (#291)
Browse files Browse the repository at this point in the history
* feat: add first version to compute accelerations in segment solution

* refactor: address comments on structure and naming

* refactor: functions and args

* test: add cpp tests

* feat: add bindings and test

* cfeat: address great feedback and use statebuilder

* chore: reoorg + suggestion

* test: reduce test with eigen

* test: try once more
  • Loading branch information
Derollez authored Dec 14, 2023
1 parent eedcef5 commit f37a2ad
Show file tree
Hide file tree
Showing 5 changed files with 502 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory_Segment(pybind11::module&
using ostk::physics::time::Duration;

using ostk::astro::trajectory::state::NumericalSolver;
using ostk::astro::trajectory::state::CoordinatesSubset;
using ostk::astro::trajectory::Segment;
using ostk::astro::Dynamics;

Expand Down Expand Up @@ -170,6 +171,57 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory_Segment(pybind11::module&
)doc"
)
.def(
"get_dynamics_contribution",
&Segment::Solution::getDynamicsContribution,
arg("dynamics"),
arg("frame"),
arg("coordinates_subsets") = Array<Shared<const CoordinatesSubset>>::Empty(),
R"doc(
Compute the contribution of the provided dynamics in the provided frame for all states associated with the segment.
Args:
dynamics (Dynamics): The dynamics.
frame (Frame): The frame.
coordinates_subsets (list[CoordinatesSubset], optional): A subset of the dynamics writing coordinates subsets to consider.
Returns:
MatrixXd: The matrix of dynamics contributions for the selected coordinates subsets of the dynamics.
)doc"
)
.def(
"get_dynamics_acceleration_contribution",
&Segment::Solution::getDynamicsAccelerationContribution,
arg("dynamics"),
arg("frame"),
R"doc(
Compute the contribution of the provided dynamics to the acceleration in the provided frame for all states associated with the segment.
Args:
dynamics (Dynamics): The dynamics.
frame (Frame): The frame.
Returns:
np.ndarray: The matrix of dynamics contributions to acceleration.
)doc"
)
.def(
"get_all_dynamics_contributions",
&Segment::Solution::getAllDynamicsContributions,
arg("frame"),
R"doc(
Compute the contributions of all segment's dynamics in the provided frame for all states assocated with the segment.
Args:
frame (Frame): The frame.
Returns:
dict[Dynamics, np.ndarray]: The list of matrices with individual dynamics contributions.
)doc"
)

;

Expand Down
49 changes: 49 additions & 0 deletions bindings/python/test/trajectory/test_segment.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Apache License 2.0

import pytest
import numpy as np

from ostk.physics import Environment
from ostk.physics.time import Instant
Expand Down Expand Up @@ -220,3 +221,51 @@ def test_solve(

assert solution.compute_delta_mass() is not None
assert solution.compute_delta_v(1500.0) is not None

state_frame: Frame = state.get_frame()

first_dynamics_contribution = solution.get_dynamics_contribution(
solution.dynamics[0], state_frame
)

second_dynamics_contribution = solution.get_dynamics_contribution(
solution.dynamics[1], state_frame
)

third_dynamics_contribution = solution.get_dynamics_contribution(
solution.dynamics[2], state_frame
)

assert first_dynamics_contribution is not None
assert second_dynamics_contribution is not None
assert third_dynamics_contribution is not None
assert first_dynamics_contribution.shape == (len(solution.states), 3)
assert second_dynamics_contribution.shape == (len(solution.states), 3)
assert third_dynamics_contribution.shape == (len(solution.states), 4)

all_contributions = solution.get_all_dynamics_contributions(state_frame)
assert len(all_contributions) == len(solution.dynamics)

assert all_contributions is not None
assert isinstance(all_contributions, dict)
assert np.array_equal(
all_contributions[solution.dynamics[0]], first_dynamics_contribution
)
assert np.array_equal(
all_contributions[solution.dynamics[1]], second_dynamics_contribution
)
assert np.array_equal(
all_contributions[solution.dynamics[2]], third_dynamics_contribution
)

acceleration_contribution = solution.get_dynamics_acceleration_contribution(
solution.dynamics[1], state_frame
)
assert acceleration_contribution is not None
assert acceleration_contribution.shape == (len(solution.states), 3)
assert isinstance(acceleration_contribution, np.ndarray)

with pytest.raises(Exception):
solution.get_dynamics_acceleration_contribution(
third_dynamics_contribution, state_frame
)
96 changes: 90 additions & 6 deletions include/OpenSpaceToolkit/Astrodynamics/Trajectory/Segment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
#define __OpenSpaceToolkit_Astrodynamics_Trajectory_Segment__

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

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

#include <OpenSpaceToolkit/Physics/Time/Duration.hpp>
#include <OpenSpaceToolkit/Physics/Time/Instant.hpp>

Expand All @@ -24,9 +27,12 @@ namespace trajectory
{

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

using ostk::math::object::MatrixXd;

using ostk::physics::time::Instant;
using ostk::physics::time::Duration;
using ostk::physics::units::Mass;
Expand All @@ -37,7 +43,7 @@ using ostk::astro::Dynamics;
using ostk::astro::dynamics::Thruster;
using ostk::astro::EventCondition;

/// @brief Represent a propagation segment for astrodynamics purposes
/// @brief Represent a propagation segment for astrodynamics purposes

class Segment
{
Expand All @@ -51,6 +57,15 @@ class Segment
struct Solution
{
public:
/// @brief Constructor
///
/// @param [in] aName Name of the segment
/// @param [in] aDynamicsArray Array of dynamics
/// @param [in] aStates Array of states for the segment
/// @param [in] aConditionIsSatisfied True if the event condition is satisfied
/// @param [in] aSegmentType Type of segment
/// @return An instance of Solution

Solution(
const String& aName,
const Array<Shared<Dynamics>>& aDynamicsArray,
Expand All @@ -59,25 +74,94 @@ class Segment
const Segment::Type& aSegmentType
);

String name; /// Name of the segment.
Array<Shared<Dynamics>> dynamics; /// List of dynamics used.
Array<State> states; /// Array of states for the segment.
bool conditionIsSatisfied; /// True if the event condition is satisfied.
Segment::Type segmentType; /// Type of segment.
/// @brief Access Start Instant
/// @return Start Instant

const Instant& accessStartInstant() const;

/// @brief Access end instant
/// @return End Instant

const Instant& accessEndInstant() const;

/// @brief Get initial mass
/// @return Initial mass

Mass getInitialMass() const;

/// @brief Get final mass
/// @return Final mass

Mass getFinalMass() const;

/// @brief Get propagation duration
/// @return Propagation duration

Duration getPropagationDuration() const;

/// @brief Compute delta V
///
/// @param [in] aSpecificImpulse Specific impulse
/// @return Delta V

Real computeDeltaV(const Real& aSpecificImpulse) const;

/// @brief Compute delta mass
/// @return Delta mass

Mass computeDeltaMass() const;

/// @brief Get dynamics contribution
///
/// @param [in] aDynamicsSPtr Dynamics
/// @param [in] aFrameSPtr Frame
/// @param [in] aCoordinatesSubsetSPtrArray Array of coordinates subsets
/// @return Dynamics contribution

MatrixXd getDynamicsContribution(
const Shared<Dynamics>& aDynamicsSPtr,
const Shared<const Frame>& aFrameSPtr,
const Array<Shared<const CoordinatesSubset>>& aCoordinatesSubsetSPtrArray =
Array<Shared<const CoordinatesSubset>>::Empty()
) const;

/// @brief Get dynamics acceleration contribution
///
/// @param [in] aDynamicsSPtr Dynamics
/// @param [in] aFrameSPtr Frame
/// @return Dynamics acceleration contribution

MatrixXd getDynamicsAccelerationContribution(
const Shared<Dynamics>& aDynamicsSPtr, const Shared<const Frame>& aFrameSPtr
) const;

/// @brief Get all segment dynamics contributions
///
/// @param [in] aFrameSPtr Frame
/// @return All segment dynamics contributions

Map<Shared<Dynamics>, MatrixXd> getAllDynamicsContributions(const Shared<const Frame>& aFrameSPtr) const;

/// @brief Print the segment solution
///
/// @param [in] anOutputStream An output stream
/// @param [in] (optional) displayDecorators If true, display decorators

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

/// @brief Output stream operator
///
/// @param [in] anOutputStream An output stream
/// @param [in] aSolution A Solution
/// @return An output stream

friend std::ostream& operator<<(std::ostream& anOutputStream, const Solution& aSolution);

String name; /// Name of the segment.
Array<Shared<Dynamics>> dynamics; /// List of dynamics used.
Array<State> states; /// Array of states for the segment.
bool conditionIsSatisfied; /// True if the event condition is satisfied.
Segment::Type segmentType; /// Type of segment.
};

/// @brief Output stream operator
Expand Down
Loading

0 comments on commit f37a2ad

Please sign in to comment.