diff --git a/include/ale/InterpUtils.h b/include/ale/InterpUtils.h index a9d465cf69c2c8f22d98a45b03f73485e63fdd60..6251746337d64e3170847c96bd5a3221bf4f1da4 100644 --- a/include/ale/InterpUtils.h +++ b/include/ale/InterpUtils.h @@ -7,18 +7,21 @@ namespace ale { + // Interpolation enum for defining different methods of interpolating rotations enum RotationInterpolation { - SLERP, // Spherical interpolation - NLERP // Normalized linear interpolation + // Spherical linear interpolation + SLERP, + // Normalized linear interpolation + NLERP }; - /// Interpolation enum for defining different methods of interpolation + // Interpolation enum for defining different methods of interpolating in R enum PositionInterpolation { - /// Interpolate using linear interpolation + // Interpolate using linear interpolation LINEAR = 0, - /// Interpolate using a cubic spline + // Interpolate using a cubic spline SPLINE = 1, - /// Interpolate using Lagrange polynomials up to 8th order + // Interpolate using Lagrange polynomials up to 8th order LAGRANGE = 2, }; @@ -28,6 +31,8 @@ namespace ale { * @param x The first value. * @param y The second value. * @param t The distance to interpolate. 0 is x and 1 is y. + * + * @return The interpolated value */ double linearInterpolate(double x, double y, double t); @@ -37,9 +42,20 @@ namespace ale { * @param x The first vectors. * @param y The second vectors. * @param t The distance to interpolate. 0 is x and 1 is y. + * + * @return The interpolated vector */ std::vector<double> linearInterpolate(const std::vector<double> &x, const std::vector<double> &y, double t); + /** + * Linearly interpolate between two 3D vectors. + * + * @param x The first vectors. + * @param y The second vectors. + * @param t The distance to interpolate. 0 is x and 1 is y. + * + * @return The interpolated vector + */ Vec3d linearInterpolate(const Vec3d &x, const Vec3d &y, double t); /** @@ -47,6 +63,7 @@ namespace ale { * * @param times The ordered vector of times to search. Must have at least 2 times. * @param interpTime The time to search for the interpolation index of. + * * @return int The index of the time that comes before interpTime. If there is * no time that comes before interpTime, then returns 0. If all * times come before interpTime, then returns the second to last @@ -56,39 +73,81 @@ namespace ale { /** * Merge, sort, and remove duplicates from two vectors + * + * @param x The first vector to merge + * @param y The second vector to merge + * + * @return A new vector containing unique, sorted values from the two input vectors */ - std::vector<double> orderedVecMerge(const std::vector<double> &x, const std::vector<double> &y); - - - /** The following helper functions are used to calculate the reduced states cache and cubic hermite - to interpolate over it. They were migrated, with minor modifications, from - Isis::NumericalApproximation **/ - - /** Evaluates a cubic hermite at time, interpTime, between the appropriate two points in x. **/ - double evaluateCubicHermite(const double interpTime, const std::vector<double>& derivs, - const std::vector<double>& x, const std::vector<double>& y); - - /** Evaluate velocities using a Cubic Hermite Spline at a time a, within some interval in x, **/ - double evaluateCubicHermiteFirstDeriv(const double interpTime, const std::vector<double>& deriv, - const std::vector<double>& times, const std::vector<double>& y); - - double lagrangeInterpolate(const std::vector<double>& times, const std::vector<double>& values, - double time, int order=8); - double lagrangeInterpolateDerivative(const std::vector<double>& times, const std::vector<double>& values, - double time, int order=8); - - /** - *@brief Interpolates the spacecraft's position along a path generated from a set of points, - times, and a time of observation - *@param points A double vector of points - *@param times A double vector of times - *@param time A double to use as the time of observation - *@param interp An interpolation enum dictating what type of interpolation to use - *@param d The order of the derivative to generate when interpolating - (Currently supports 0, 1, and 2) - *@return + std::vector<double> orderedVecMerge(const std::vector<double> &x, const std::vector<double> &y); + + /** + * Evaluates a cubic hermite spline at an input time. + * + * migrated from Isis::NumericalApproximation + * + * @param interpTime The time to interpolate at, should be in the same units as x + * @param x The times of the spline nodes + * @param derivs The derivatives of the spline at the nodes + * @param y The values of the spline at the nodes + * + * @return The value of the spline at the input time + */ + double evaluateCubicHermite(const double interpTime, const std::vector<double>& derivs, + const std::vector<double>& x, const std::vector<double>& y); + + /** + * Evaluate the first derivative of a cubic hermite spline at an input time. + * + * @param interpTime The time to interpolate at, should be in the same units as x + * @param x The times of the spline nodes + * @param derivs The derivatives of the spline at the nodes + * @param y The values of the spline at the nodes + * + * @return The first derivative of the spline at the input time + */ + double evaluateCubicHermiteFirstDeriv(const double interpTime, const std::vector<double>& deriv, + const std::vector<double>& times, const std::vector<double>& y); + + /** + * Interpolate a set of values using lagrange polynomials. + * + * @param times The vector of times to interpolate over + * @param values The vector of values to interpolate between + * @param time The time to interpolate at + * @param order The order of the lagrange polynomials to use + * + * @return The interpolated value + */ + double lagrangeInterpolate(const std::vector<double>& times, const std::vector<double>& values, + double time, int order=8); + + /** + * Interpolate the first derivative of a set of values using lagrange polynomials. + * + * @param times The vector of times to interpolate over + * @param values The vector of values to interpolate between + * @param time The time to interpolate at + * @param order The order of the lagrange polynomials to use + * + * @return The interpolated first derivative + */ + double lagrangeInterpolateDerivative(const std::vector<double>& times, const std::vector<double>& values, + double time, int order=8); + + /** + * @brief Interpolates a value from a set of points and times + * + * @param points A vector of points + * @param times A vector of times + * @param time The time to interpolate at + * @param interp An interpolation enum dictating what type of interpolation to use + * @param d The order of the derivative to generate when interpolating + * (Currently supports 0, 1, and 2) + * + * @return The interpolated value */ - double interpolate(std::vector<double> points, std::vector<double> times, double time, PositionInterpolation interp, int d); + double interpolate(std::vector<double> points, std::vector<double> times, double time, PositionInterpolation interp, int d); } diff --git a/include/ale/Orientations.h b/include/ale/Orientations.h index 0200f758a7f7b13b2842c49493eb6067bcb01048..5c25aa48c573b6ab8db2e3401fcbd831677eb9cf 100644 --- a/include/ale/Orientations.h +++ b/include/ale/Orientations.h @@ -16,6 +16,14 @@ namespace ale { /** * Construct an orientation object give a set of rotations * and optionally angular velocities at specific times. + * + * @param rotations The rotations defining the Orientations + * @param times The times for the rotations and angular velocities + * @param avs The angular velocity at each time + * @param constRot An additional constant rotation that is applied after + * the time dependent rotations + * @param const_frames The frame ids that constRot rotates through + * @param time_dependent_frames The frame ids that rotations rotate through */ Orientations( const std::vector<Rotation> &rotations, @@ -32,17 +40,37 @@ namespace ale { ~Orientations() {}; /** - * Const accessor methods + * Get the vector of time dependent rotations */ std::vector<Rotation> getRotations() const; + /** + * Get the vector of angular velocities + */ std::vector<ale::Vec3d> getAngularVelocities() const; + /** + * Get the vector of times + */ std::vector<double> getTimes() const; + /** + * Get the frames that the constant rotation rotates through + */ std::vector<int> getConstantFrames() const; + /** + * Get the frames that the time dependent rotations rotate through + */ std::vector<int> getTimeDependentFrames() const; + /** + * Get the constant rotation + */ Rotation getConstantRotation() const; /** * Get the time dependent component of the interpolated rotation at a specific time. + * + * @param time The time to interpolate at + * @param interpType The type of interpolation to use + * + * @return The time dependent rotation at the input time */ Rotation interpolateTimeDep( double time, @@ -51,6 +79,11 @@ namespace ale { /** * Get the interpolated rotation at a specific time. + * + * @param time The time to interpolate at + * @param interpType The type of interpolation to use + * + * @return The full rotation at the input time */ Rotation interpolate( double time, @@ -58,10 +91,26 @@ namespace ale { ) const; /** - * Get the interpolated angular velocity at a specific time + * Get the interpolated angular velocity at a specific time. + * Angular velocities are interpolated linearly to match up with the assumptions + * of SLERP. + * + * @param time The time to interpolate the angular velocity at + * + * @return The angular velocity at the input time */ ale::Vec3d interpolateAV(double time) const; + /** + * Rotate a 3d vector at a specific time + * + * @param time The time to rotate the vector at + * @param vector The input vector to rotate + * @param interpType The interpolation type to use + * @param invert If the rotation should be inverted + * + * @return The rotated 3d vector + */ ale::Vec3d rotateVectorAt( double time, const ale::Vec3d &vector, @@ -70,7 +119,14 @@ namespace ale { ) const; /** - * Rotate a position or state vector at a specific time + * Rotate a state vector at a specific time + * + * @param time The time to rotate the vector at + * @param state The input state to rotate + * @param interpType The interpolation type to use + * @param invert If the rotation should be inverted + * + * @return The rotated state */ ale::State rotateStateAt( double time, @@ -80,23 +136,37 @@ namespace ale { ) const; /** - * Add an additional constant multiplication. - * This is equivalent to left multiplication by a constant rotation + * Add an additional constant rotation after this. + * This is equivalent to left multiplication by a constant rotation. + * + * @param addedConst The additional constant rotation to apply after this + * + * @return A refernce to this after the update */ Orientations &addConstantRotation(const Rotation &addedConst); /** - * Multiply this orientation by another orientation + * Multiply this set of orientations by another set of orientations + * + * @param rhs The set of orientations to apply before this set + * + * @return A refernce to this after the update */ Orientations &operator*=(const Orientations &rhs); /** - * Multiply this orientation by a constant rotation + * Add an additional constant rotation before this. + * This is equivalent to right multiplication by a constant rotation. + * + * @param rhs The additional constant rotation to apply before this + * + * @return A refernce to this after the update */ Orientations &operator*=(const Rotation &rhs); /** - * Invert the orientations. + * Invert the set orientations. + * * Note that inverting a set of orientations twice does not result in * the original orientations. the constant rotation is applied after the * time dependent rotation. This means in the inverse, the constant @@ -105,20 +175,51 @@ namespace ale { * Then, the original constant rotations cannot be recovered when inverting * again. The set of orientations will still operate the same way, but its * internal state will not be the same. + * + * Similarly, the angular velocities will not be the same as we do not assume + * the angular acceleration to be continuous. + * + * @return A new set of orientations that are inverted. */ Orientations inverse() const; private: - std::vector<Rotation> m_rotations; - std::vector<ale::Vec3d> m_avs; - std::vector<double> m_times; - std::vector<int> m_timeDepFrames; - std::vector<int> m_constFrames; - Rotation m_constRotation; + std::vector<Rotation> m_rotations; //!< The set of time dependent rotations. + std::vector<ale::Vec3d> m_avs; //!< The set of angular velocities. Empty if there are no angular velocities. + std::vector<double> m_times; //!< The set of times + std::vector<int> m_timeDepFrames; //!< The frame IDs that the time dependent rotations rotate through. + std::vector<int> m_constFrames; //!< The frame IDs that the constant rotation rotates through. + Rotation m_constRotation; //!< The constant rotation applied after the time dependent rotations. }; + /** + * Apply a constant rotation before a set of Orientations + * + * @param lhs The set of Orientations + * @param rhs The constant rotation + * + * @return A new set of orientations combining the constant rotation and old orientations + */ Orientations operator*(Orientations lhs, const Rotation &rhs); + + /** + * Apply a constant rotation after a set of Orientations + * + * @param lhs The constant rotation + * @param rhs The set of Orientations + * + * @return A new set of orientations combining the constant rotation and old orientations + */ Orientations operator*(const Rotation &lhs, Orientations rhs); + + /** + * Apply two Orientations in a row + * + * @param lhs The second orientation to apply + * @param rhs The first orientation to apply + * + * @return A new set of orientations combining both orientations + */ Orientations operator*(Orientations lhs, const Orientations &rhs); } diff --git a/include/ale/States.h b/include/ale/States.h index 5c90994fd7cc7e34573560ef6337ff55116f48ca..bfd3cc6502b20a414dcd47bc4e6108ab8bb0c343 100644 --- a/include/ale/States.h +++ b/include/ale/States.h @@ -16,7 +16,7 @@ namespace ale { Vec3d position; Vec3d velocity; - // Accepts a {x, y, z, vx, vy, vz} vector + // Creates a state from a {x, y, z, vx, vy, vz} vector State(const std::vector<double>& vec) { if (vec.size() != 6) { throw std::invalid_argument("Input vector must have 6 entries."); @@ -25,14 +25,20 @@ namespace ale { velocity = {vec[3], vec[4], vec[5]}; }; + // Creates a state with only a position State(Vec3d position) : position(position) { velocity = {std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()}; }; + + // Creates a state with a position and velocity State(Vec3d position, Vec3d velocity) : position(position), velocity(velocity) {}; + + // Creates an un-initialized state State() {}; + // If the velocity for the state has been initialized bool hasVelocity() const { return !(std::isnan(velocity.x) || std::isnan(velocity.y) || std::isnan(velocity.z)); } @@ -41,28 +47,44 @@ namespace ale { class States { public: // Constructors + /** + * Creates an empty States object + */ States(); + + /** + * Creates a States object from a set of times and positions + */ States(const std::vector<double>& ephemTimes, const std::vector<Vec3d>& positions, int refFrame=1); + /** + * Creates a States object from a set of times and positions + */ States(const std::vector<double>& ephemTimes, const std::vector<std::vector<double>>& positions, int refFrame=1); + /** + * Creates a States object from a set of times, positions, and velocities + */ States(const std::vector<double>& ephemTimes, const std::vector<Vec3d>& positions, const std::vector<Vec3d>& velocities, int refFrame=1); + /** + * Creates a States object from a set of times, states + */ States(const std::vector<double>& ephemTimes, const std::vector<State>& states, int refFrame=1); ~States(); // Getters - std::vector<State> getStates() const; //! Returns state vectors (6-element positions&velocities) - std::vector<Vec3d> getPositions() const; //! Returns the current positions - std::vector<Vec3d> getVelocities() const; //! Returns the current velocities - std::vector<double> getTimes() const; //! Returns the current times - int getReferenceFrame() const; //! Returns reference frame as NAIF ID - bool hasVelocity() const; //! Returns true if any velocities have been provided + std::vector<State> getStates() const; //!< Returns state vectors (6-element positions&velocities) + std::vector<Vec3d> getPositions() const; //!< Returns the current positions + std::vector<Vec3d> getVelocities() const; //!< Returns the current velocities + std::vector<double> getTimes() const; //!< Returns the current times + int getReferenceFrame() const; //!< Returns reference frame as NAIF ID + bool hasVelocity() const; //!< Returns true if any velocities have been provided /** * Returns a single state by interpolating state. @@ -73,7 +95,7 @@ namespace ale { * @param time Time to get a value at * @param interp Interpolation type to use. Will be ignored if cache is minimized. * - * @return State + * @return The interpolated state */ State getState(double time, PositionInterpolation interp=LINEAR) const; @@ -98,6 +120,8 @@ namespace ale { * Adapted from Isis::SpicePosition::reduceCache(). * * @param tolerance Maximum error between hermite approximation and original value. + * + * @return A new set of states that has been downsized. */ States minimizeCache(double tolerance=0.01); @@ -114,13 +138,13 @@ namespace ale { * @param baseTime Scaled base time for fit * @param timeScale Time scale for fit. * - * @return std::vector<int> + * @return The indices that should be kept to downsize the set of States */ std::vector<int> hermiteIndices(double tolerance, std::vector <int> indexList, double baseTime, double timeScale); - std::vector<State> m_states; //! Represent as states internally to keep pos, vel together - std::vector<double> m_ephemTimes; //! Time in seconds - int m_refFrame; //! Naif IDs for reference frames + std::vector<State> m_states; //!< The internal states cache + std::vector<double> m_ephemTimes; //!< The times for the states cache + int m_refFrame; //!< Naif ID for the reference frame the states are in }; }