Skip to content

feat: distinguish between profile target velocity and ground velocity #561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

apaletta3
Copy link
Contributor

@apaletta3 apaletta3 commented May 19, 2025

Non-breaking change that moves the yaw compensation functionality over to TargetGroundVelocity, while the leaving the TargetVelocity to be used for non-yaw compensated profiles. This more clearly indicates the intent of each target type, since yaw compensation doesn't align the clocking axis with the target's general velocity, it aligns it with the target's ground velocity.

It also adds more thorough tests for simple geometric cases of target trajectory position, velocity, and sliding target ground velocity for a simple polar orbit

Summary by CodeRabbit

  • New Features

    • Introduced a new target type for aligning with the sliding ground velocity vector, allowing profiles to compensate for the rotation of the referenced celestial body.
  • Bug Fixes

    • Improved consistency in frame usage for state transformations and coordinate access, enhancing accuracy in direction computations.
  • Tests

    • Added and restructured tests to cover the new sliding ground velocity target type and improved parameterization for alignment and constraint logic.
    • Enhanced yaw compensation tests with additional profile variants and reference data for increased reliability.

@apaletta3 apaletta3 self-assigned this May 19, 2025
Copy link
Contributor

coderabbitai bot commented May 19, 2025

Walkthrough

A new target type, TargetSlidingGroundVelocity, is introduced throughout the astrodynamics flight profile module, enabling alignment with the sliding ground velocity vector of a trajectory. This includes updates to enumerations, factory methods, vector computation logic, and comprehensive unit tests. Frame usage is unified under a default profile frame, and tests are expanded and refactored.

Changes

File(s) Change Summary
bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Flight/Profile.cpp
include/OpenSpaceToolkit/Astrodynamics/Flight/Profile.hpp
Added TargetSlidingGroundVelocity to Profile::TargetType enum. Introduced TrajectoryTarget::TargetSlidingGroundVelocity factory method. Updated documentation and declarations to support the new target type. Added private static method for sliding ground velocity vector computation and moved existing velocity vector method for clarity.
src/OpenSpaceToolkit/Astrodynamics/Flight/Profile.cpp Implemented TargetSlidingGroundVelocity logic: new factory method, vector computation, and error handling. Introduced DEFAULT_PROFILE_FRAME for consistent frame usage. Updated all relevant direction vector computations to use the default frame. Extended alignment and constraint logic to handle the new target type.
test/OpenSpaceToolkit/Astrodynamics/Flight/Profile.test.cpp Added and refactored tests for TargetSlidingGroundVelocity. Expanded parameterized tests for alignment and constraint logic, covering new and existing trajectory target types. Improved test structure and consistency. Renamed and enhanced yaw compensation test to compare multiple profile variants against reference data.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Profile
    participant TrajectoryTarget
    participant Trajectory
    participant Frame

    User->>Profile: AlignAndConstrain(target, clockingTarget, angle)
    Profile->>TrajectoryTarget: (If target is TargetSlidingGroundVelocity) Compute direction
    TrajectoryTarget->>Trajectory: Get state/velocity at time
    Trajectory->>Frame: Transform velocity to default profile frame
    Frame-->>TrajectoryTarget: Returns transformed velocity
    TrajectoryTarget-->>Profile: Returns normalized sliding ground velocity vector
    Profile-->>User: Returns orientation aligning axis with computed vector
Loading

Poem

In the fields of stars where satellites play,
A new ground velocity target joins the ballet.
Sliding swift with Earth's own spin,
Our code aligns, precise and thin.
With tests that hop and yaw with glee,
The rabbit cheers: "Astrodynamics, now with extra velocity!"
🐇✨

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ Faster reviews with caching

CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.
Enjoy the performance boost—your workflow just got faster.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 399bf95 and 91670bd.

📒 Files selected for processing (2)
  • src/OpenSpaceToolkit/Astrodynamics/Flight/Profile.cpp (4 hunks)
  • test/OpenSpaceToolkit/Astrodynamics/Flight/Profile.test.cpp (10 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/OpenSpaceToolkit/Astrodynamics/Flight/Profile.cpp
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build Development Image / Build Development Image
🔇 Additional comments (13)
test/OpenSpaceToolkit/Astrodynamics/Flight/Profile.test.cpp (13)

30-30: Clean include addition for the Nadir trajectory model.

This is an appropriate addition to support the new trajectory model needed for testing the sliding ground velocity functionality.


75-75: Properly added using directive for Nadir model.

Correctly adds the corresponding namespace usage for the Nadir trajectory model.


855-858: Well-implemented error test case for new TargetSlidingGroundVelocity factory method.

This test verifies that the new factory method correctly validates its input by throwing the appropriate exception when constructed with an undefined trajectory, matching the behavior of existing target factory methods.


871-872: Correct validation test for TargetSlidingGroundVelocity with valid trajectory.

This test confirms that the new factory method behaves properly when provided with valid input, maintaining consistency with the existing target factory methods.


912-913: Appropriate test rename to clarify purpose.

Renaming from "YawCompensation" to "YawCompensationOrekit" provides better clarity about the test's purpose and reference source.


914-966: Well-structured test setup comparing three different profile configurations.

This setup creates three profiles for comprehensive comparison testing:

  1. targetSlidingGroundVelocityClockedProfile: Uses the new TargetSlidingGroundVelocity (yaw-compensated)
  2. targetVelocityClockedProfile: Uses TargetVelocity (non-yaw-compensated)
  3. satelliteVelocityClockedProfile: Uses simple velocity target

The test demonstrates the differences between these targeting approaches, effectively testing the new functionality.


967-993: Thorough validation against Orekit reference quaternions.

The test compares each profile's orientation against Orekit reference quaternions with appropriate tolerance levels. The sliding ground velocity quaternion is validated with the strictest tolerance (1e-8), while the target velocity quaternion uses a more relaxed tolerance (1e-3) since it's comparing different quaternion types.


995-1001: Good quantitative measurement of angular difference between approaches.

The test explicitly verifies the angular difference (3.8°) between the sliding ground velocity and satellite velocity orientations, providing a concrete measurement of the yaw compensation effect.


1244-1319: Thorough testing of various alignment and clocking combinations.

The test methodically validates:

  1. Error cases for invalid axis/target combinations
  2. Proper orientation generation for valid combinations
  3. Alignment of body axes with expected directions
  4. Special handling for more complex target combinations like sun pointing

This ensures all target type combinations work correctly with the new sliding ground velocity functionality.


1321-1349: Comprehensive instantiation of test cases for simple target types.

The test suite instantiation provides good coverage of alignment and clocking axis combinations with different target types, ensuring that the new functionality works correctly in various scenarios.


1351-1363: Well-structured parameterized test class for trajectory target types.

This test class provides a clean setup for testing the new trajectory-based target types, using a simple polar orbit as the test case to isolate the effects of each target type.


1365-1412: Excellent side-by-side comparison of all trajectory target types.

The test creates and compares three key targeting approaches:

  1. TargetPosition - aiming at the target's position
  2. TargetVelocity - aiming along the target's velocity vector
  3. TargetSlidingGroundVelocity - aiming along the target's ground-relative velocity

This thorough comparison validates that each targeting method produces the expected orientation with a consistent tolerance of 1e-3.


1414-1455: Comprehensive test instantiation with geometric test cases.

The test parameters cleverly use four key points in a polar orbit (ascending node, north pole, descending node, south pole) to validate orientation behavior. The expected direction vectors clearly demonstrate the differences between:

  • Standard velocity targeting
  • Sliding ground velocity targeting (which adjusts for Earth's rotation)

Of note, at the poles, both velocity vectors are identical (as expected since there's no rotational component at the poles).

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

codecov bot commented May 19, 2025

Codecov Report

Attention: Patch coverage is 94.11765% with 1 line in your changes missing coverage. Please review.

Project coverage is 91.79%. Comparing base (ce7913f) to head (91670bd).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
.../OpenSpaceToolkit/Astrodynamics/Flight/Profile.cpp 94.11% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #561      +/-   ##
==========================================
- Coverage   91.81%   91.79%   -0.02%     
==========================================
  Files         106      106              
  Lines       10017    10031      +14     
==========================================
+ Hits         9197     9208      +11     
- Misses        820      823       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@apaletta3 apaletta3 marked this pull request as ready for review May 19, 2025 22:58
@apaletta3 apaletta3 force-pushed the fix/profile-frames-and-target-velocity branch from f3d464d to 988bba8 Compare May 20, 2025 07:53
@apaletta3 apaletta3 force-pushed the feat/distinguish-between-profile-target-velocity-and-ground-velocity branch from 6a21d31 to 42b005e Compare May 20, 2025 08:47
Base automatically changed from fix/profile-frames-and-target-velocity to main May 20, 2025 09:12
@apaletta3 apaletta3 force-pushed the feat/distinguish-between-profile-target-velocity-and-ground-velocity branch from 104ad3f to 399bf95 Compare May 20, 2025 14:06
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

🧹 Nitpick comments (7)
bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Flight/Profile.cpp (3)

61-65: New enum value exposed correctly – consider enriching the description

TargetSlidingGroundVelocity is now reachable from Python – nice!
A short note that this target compensates for body rotation (a-la yaw compensation) would make the purpose unambiguous for end-users who are not familiar with the C++ docs.


146-151: Doc-string still a bit vague about “scan direction”

“Scan direction” might not ring a bell for everyone. A minimal clarification such as “… i.e. the instantaneous velocity vector of the target in its own inertial frame – no yaw-compensation applied” would remove any guesswork.


152-162: Mirror the yaw-compensation note in the new factory’s doc

Because the ground velocity target is the yaw-compensated counterpart of target_velocity, explicitly stating that relationship in the Python doc helps prevent misuse.

Example tweak:

-Create a target, which produces a vector pointing along the ground velocity vector ...
+Create a target that returns the **yaw-compensated** ground-velocity vector (i.e. the
+scan-direction after compensating for the body's rotation) ...
include/OpenSpaceToolkit/Astrodynamics/Flight/Profile.hpp (1)

148-167: Minor wording tweak for Doxygen comments

Both velocity-related factory methods talk about “scan direction”.
For TargetVelocity you already note “will not be yaw compensated”; it would be useful to mirror the wording for the new method (“will be yaw compensated”) for readers skimming only the header.

src/OpenSpaceToolkit/Astrodynamics/Flight/Profile.cpp (1)

34-34: Constant default frame – double-check static-initialisation order

Frame::GCRF() indirectly touches the frame manager singleton. Creating the shared
pointer in a namespace-scope static is usually fine, but if another TU’s static
needs DEFAULT_PROFILE_FRAME during its own initialisation the “static initialisation
order fiasco” could bite. One-liner fix is to wrap it in a function:

static const Shared<const Frame>& DefaultProfileFrame()
{
    static const auto kFrame = Frame::GCRF();
    return kFrame;
}

Then replace uses with DefaultProfileFrame().

test/OpenSpaceToolkit/Astrodynamics/Flight/Profile.test.cpp (2)

1200-1253: Remove unreachable break; statements inside getExpectedDirectionVector_

Every return already exits the lambda; the subsequent break; is never executed and may trigger compiler warnings (especially with -Werror).
Cleaning these out improves readability and eliminates dead code.

-    case Profile::TargetType::GeocentricNadir:
-        return -aState.getPosition().getCoordinates().normalized();
-        break;
+    case Profile::TargetType::GeocentricNadir:
+        return -aState.getPosition().getCoordinates().normalized();-            return (sun.getPositionIn(Frame::GCRF(), aState.accessInstant()).getCoordinates() -
-                    aState.getPosition().getCoordinates())
-                .normalized();
-            break;
+            return (sun.getPositionIn(Frame::GCRF(), aState.accessInstant()).getCoordinates() -
+                    aState.getPosition().getCoordinates())
+                .normalized();

Apply to all cases (Moon, default) in this switch.


1353-1359: Derive parameter-name strings without relying on enum underlying values

Casting enums to int is fragile if the underlying type changes or values are reordered. Prefer std::to_string(static_cast<std::underlying_type_t<Enum>>(…)) or stringify the enum via a helper.

-return "Axis" + std::to_string(static_cast<int>(std::get<0>(paramInfo.param))) + …
+constexpr auto toIndex = [](auto e)
+{
+    return std::to_string(static_cast<std::underlying_type_t<std::decay_t<decltype(e)>>>(e));
+};
+return "Axis" + toIndex(std::get<0>(paramInfo.param)) + …

This keeps the code valid even if the enum’s underlying type is changed to std::uint8_t, etc.

🛑 Comments failed to post (2)
include/OpenSpaceToolkit/Astrodynamics/Flight/Profile.hpp (1)

93-107: 🛠️ Refactor suggestion

⚠️ Potential issue

Adding a middle enum entry silently shifts underlying integral values

TargetSlidingGroundVelocity is inserted before Sun, Moon, …
If any serialized data, hashing, or switch-statements outside this library rely on the
previous integer mapping (e.g. Sun used to be 5, now it’s 6) this becomes an
ABI / data-format breaking change even though the PR is labelled non-breaking.

Two typical mitigations:

enum class TargetType
{
-   GeodeticNadir = 1,
-   ...
-   TargetVelocity = 4,
-   TargetSlidingGroundVelocity = 5,
-   Sun = 6,
+   GeodeticNadir = 1,
+   ...
+   TargetVelocity = 4,
+   TargetSlidingGroundVelocity = 5,   // NEW but explicit
+   Sun = 6,                           // keeps previous value

or append the new value at the end of the enum list.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In include/OpenSpaceToolkit/Astrodynamics/Flight/Profile.hpp around lines 93 to
107, the insertion of TargetSlidingGroundVelocity before Sun shifts the integral
values of subsequent enum entries, causing potential ABI and data-format breaks.
To fix this, move TargetSlidingGroundVelocity to the end of the enum list after
Custom to preserve the original integer mappings of existing entries and avoid
breaking changes.
src/OpenSpaceToolkit/Astrodynamics/Flight/Profile.cpp (1)

498-503: 🛠️ Refactor suggestion

Guard against zero-magnitude target velocity

ComputeTargetVelocityVector will normalize() any vector – but if the target is
momentarily stationary the call will throw deep inside Eigen. A consistency check
mirroring the one you added for sliding ground velocity would make the behaviour
explicit and symmetrical.

+if (targetVelocityCoordinates.isZero())
+{
+    throw ostk::core::error::RuntimeError(
+        "Cannot compute Target Velocity Vector: target speed is zero."
+    );
+}
 return targetVelocityCoordinates.normalized();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    const Vector3d targetVelocityCoordinates =
        aTrajectory.getStateAt(aState.accessInstant()).inFrame(DEFAULT_PROFILE_FRAME).getVelocity().accessCoordinates();

    if (targetVelocityCoordinates.isZero())
    {
        throw ostk::core::error::RuntimeError(
            "Cannot compute Target Velocity Vector: target speed is zero."
        );
    }

    return targetVelocityCoordinates.normalized();
}
🤖 Prompt for AI Agents
In src/OpenSpaceToolkit/Astrodynamics/Flight/Profile.cpp around lines 498 to
503, the code normalizes the target velocity vector without checking if its
magnitude is zero, which can cause a runtime error. Add a guard to check if the
target velocity vector's magnitude is zero before normalization; if it is zero,
handle this case explicitly (e.g., return a zero vector or handle as
appropriate) to prevent exceptions and ensure consistent behavior with the
sliding ground velocity check.

@apaletta3 apaletta3 enabled auto-merge (squash) May 20, 2025 14:07
@apaletta3 apaletta3 merged commit f5760a0 into main May 20, 2025
19 of 20 checks passed
@apaletta3 apaletta3 deleted the feat/distinguish-between-profile-target-velocity-and-ground-velocity branch May 20, 2025 17:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants