Skip to content
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

Add hw and os checks #491

Merged
merged 2 commits into from
Feb 10, 2025
Merged

Add hw and os checks #491

merged 2 commits into from
Feb 10, 2025

Conversation

KmakD
Copy link
Contributor

@KmakD KmakD commented Feb 5, 2025

Description

Added following checks in launch files:

  • Check for incorrect hardware configuration
  • Check for incorrect OS version
  • Prevent starting driver if hardware configuration is incorrect

image

Requirements

  • Code style guidelines followed
  • Documentation updated

Tests 🧪

  • Robot
  • Container
  • Simulation

Summary by CodeRabbit

  • New Features
    • Enhanced the startup process with robust hardware and operating system compatibility checks.
    • Standardized error and warning displays now alert users when system requirements are not met.
    • New launch configuration options allow users to customize the system’s behavior in response to incompatibility issues.

Copy link
Contributor

coderabbitai bot commented Feb 5, 2025

Walkthrough

The pull request enhances the launch process by introducing hardware configuration and operating system version compatibility checks. In the launch file, a new constant, function, and launch arguments have been added to evaluate and enforce a minimum OS version and proper hardware configuration. Additionally, new actions trigger warnings or halt the process based on the checks. A utility module now provides a standardized way of generating styled error and warning messages through a new error message class with associated helper functions.

Changes

File(s) Change Summary
husarion_ugv_bringup/.../bringup.launch.py Added constant MIN_REQUIRED_OS_VERSION and function check_version_compatibility for validating the OS version. Introduced new launch arguments (exit_on_wrong_hw, declare_common_dir_path_arg, declare_disable_manager_arg, declare_log_level_arg, declare_namespace_arg) and actions to handle hardware configuration and OS version checks.
husarion_ugv_utils/.../messages.py Introduced ErrorMessages class with constants (INCORRECT_HW_CONFIG, INCORRECT_OS_VERSION) and helper methods (error_msg and warning_msg) to generate styled error and warning messages.
husarion_ugv_utils/.../version_check.py Added functions extract_version_tuple and check_version_compatibility for version management, enabling the extraction of version numbers from strings and checking compatibility against a minimum required version.

Sequence Diagram(s)

sequenceDiagram
    participant Launcher as Launch File
    participant Env as Environment
    participant Validator as OS Version Check
    participant Msg as ErrorMessages

    Launcher->>Env: Retrieve current OS version
    Launcher->>Validator: Execute check_version_compatibility(os_version, MIN_REQUIRED_OS_VERSION)
    Validator-->>Launcher: Return compatibility status

    alt OS version incompatible
        Launcher->>Msg: Generate warning message (INCORRECT_OS_VERSION)
    else OS version compatible
        Note over Launcher, Validator: Continue normal launch actions
    end

    alt Hardware configuration incorrect and exit_on_wrong_hw True
        Launcher->>Msg: Generate error message (INCORRECT_HW_CONFIG)
        Launcher-->>Launcher: Trigger indefinite sleep (halt launch)
    end
Loading
✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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.

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
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.

Actionable comments posted: 0

🧹 Nitpick comments (3)
husarion_ugv_bringup/launch/bringup.launch.py (3)

45-45: Consider externalizing minimum OS version.
Defining MIN_REQUIRED_OS_VERSION = [2, 2, 0] works. However, storing such constants in a separate config file or param might simplify adjustments without modifying code.


48-68: OS version compatibility checks are clear but may be fragile.
The regex-based parsing and multi-step comparison logic works for the simple semantic format vX.Y.Z. Consider handling extra characters (e.g., -rc or build metadata) or missing segments. You might return a more detailed reason for incompatibility to guide users.


191-195: Using sleep infinity to block might be limiting.
While this effectively prevents node startup, it could consume resources indefinitely. Consider a more graceful fail or a single blocking action that clearly indicates the issue.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be0e8da and 40d595b.

📒 Files selected for processing (2)
  • husarion_ugv_bringup/launch/bringup.launch.py (3 hunks)
  • husarion_ugv_utils/husarion_ugv_utils/messages.py (2 hunks)
🔇 Additional comments (15)
husarion_ugv_bringup/launch/bringup.launch.py (12)

18-19: No issues with new imports.
The addition of os and re appears necessary for environment variable retrieval and version parsing.


21-26: Imports from husarion_ugv_utils.messages are correctly introduced.
These imports unify and standardize the way you log errors, warnings, and welcome messages.


28-34: Expanded imports from launch.actions.
Bringing in these actions (DeclareLaunchArgument, ExecuteProcess, GroupAction, IncludeLaunchDescription, TimerAction) is appropriate for controlling advanced launch flows.


35-35: Conditional imports look good.
Using IfCondition and UnlessCondition is standard for modular ROS 2 launch logic.


41-41: Use of PythonExpression is valid.
It’s a good choice for runtime boolean checks and dynamic substitutions in launch files.


71-77: Launch argument for hardware exit check is appropriate.
Defining "exit_on_wrong_hw" as a launch argument provides flexibility to either block or proceed, aligning with different deployment needs.


189-190: Environment variable default aligns with design.
Setting ROBOT_HW_CONFIG_CORRECT to "false" by default ensures the system checks are performed unless overridden.


196-202: Grouping incorrect hardware config actions is well-structured.
Leveraging error_msg and a GroupAction ensures the user is notified and the process halts as intended based on conditions.


204-208: Retrieving OS version from environment is straightforward.
Falling back to "v0.0.0" when SYSTEM_BUILD_VERSION is missing or invalid is sensible.


209-218: Warning action for incorrect OS version is sensible.
Using a warning rather than an error acknowledges that the robot might still operate, albeit in an unsupported configuration.


230-237: Conditional driver actions are cleanly toggled.
This GroupAction ensures the driver launches only when the hardware config is correct, preventing partial or erroneous startups.


240-248: Final actions list neatly integrates new checks.
Appending incorrect_hw_config_action, incorrect_os_version_action, and driver_actions into actions seamlessly ties together the updated logic in a single return.

husarion_ugv_utils/husarion_ugv_utils/messages.py (3)

48-64: Centralized error/warning strings improve maintainability.
ErrorMessages provides well-formatted constants. Consider adding a docstring to clarify their usage and whether more messages might be consolidated here.


112-115: error_msg function works well for quick stylized logs.
Currently, it uses LogInfo with red text, which is sufficient for most ROS 2 terminal outputs.


117-119: warning_msg function parallels error_msg consistently.
The consistency ensures easy integration for both error and warning messages. In future, consider whether more advanced log levels or additional context is needed.

@KmakD KmakD requested a review from rafal-gorecki February 7, 2025 07:37
Comment on lines 205 to 207
os_version_correct = PythonExpression(
f"{check_os_version_compatibility(os_version, MIN_REQUIRED_OS_VERSION)}"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

PythonExpression probably can be omitted, because os.environ is just a string

Suggested change
os_version_correct = PythonExpression(
f"{check_os_version_compatibility(os_version, MIN_REQUIRED_OS_VERSION)}"
)
os_version_correct = check_os_version_compatibility(os_version, MIN_REQUIRED_OS_VERSION)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

UnlessCondition doesn't accept bool, that's why this is wrapped with PythonExpression

exit_on_wrong_hw = LaunchConfiguration("exit_on_wrong_hw")
declare_exit_on_wrong_hw_arg = DeclareLaunchArgument(
"exit_on_wrong_hw",
default_value="false",
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not default true?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's the debate what is our default state. I assumed using docker and avoiding unnecessary restarts of it

Comment on lines 45 to 67
MIN_REQUIRED_OS_VERSION = [2, 2, 0]


def check_os_version_compatibility(version_string: str, min_required_version: list[int]) -> bool:
match = re.search(r"v(\d+\.\d+\.\d+)", version_string)

if not match:
return False

version_str = match.group(1)
version = version_str.split(".")

if int(version[0]) > min_required_version[0]:
return True

if int(version[0]) == min_required_version[0]:
if int(version[1]) > min_required_version[1]:
return True

if int(version[1]) == min_required_version[1]:
return int(version[2]) >= min_required_version[2]

return False
Copy link
Contributor

Choose a reason for hiding this comment

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

Propose to move it to *_utils and simplify it. Like in following example

import re

MIN_REQUIRED_OS_VERSION = "v2.2.2"


def extract_version_tuple(version_string: str) -> tuple[int, int, int]:
    match = re.search(r"v(\d+)\.(\d+)\.(\d+)", version_string)
    return tuple(map(int, match.groups())) if match else (0, 0, 0)

def check_os_version_compatibility(version1: str, min_required_version: str) -> bool:
    return extract_version_tuple(version1) >= extract_version_tuple(min_required_version)

# Example usage
print(check_os_version_compatibility("v1.9.5", MIN_REQUIRED_OS_VERSION))  # False
print(check_os_version_compatibility("v2.2.2", MIN_REQUIRED_OS_VERSION))  # True
print(check_os_version_compatibility("v2.3.0", MIN_REQUIRED_OS_VERSION))  # True

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is smart

@KmakD KmakD requested a review from rafal-gorecki February 7, 2025 13:32
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.

Actionable comments posted: 0

🧹 Nitpick comments (4)
husarion_ugv_utils/husarion_ugv_utils/version_check.py (2)

20-22: Add input validation and improve documentation.

The function needs input validation and better documentation:

  1. Add input validation for None/empty strings
  2. Add docstring explaining the expected format
  3. Add more specific type hints
-def extract_version_tuple(version_string: str) -> tuple[int, int, int]:
-    match = re.search(r"v(\d+)\.(\d+)\.(\d+)", version_string)
-    return tuple(map(int, match.groups())) if match else (0, 0, 0)
+def extract_version_tuple(version_string: str | None) -> tuple[int, int, int]:
+    """Extract version numbers from a version string.
+
+    Args:
+        version_string: Version string in format "vX.Y.Z" where X, Y, Z are integers
+
+    Returns:
+        tuple[int, int, int]: Version numbers as (major, minor, patch), or (0, 0, 0) if invalid
+    """
+    if not version_string:
+        return (0, 0, 0)
+    match = re.search(r"v(\d+)\.(\d+)\.(\d+)", version_string)
+    return tuple(map(int, match.groups())) if match else (0, 0, 0)

25-30: Enhance docstring with parameter and return type documentation.

The docstring should include parameter and return type documentation.

 def check_version_compatibility(version: str, min_required_version: str) -> bool:
     """
     Check if the version is compatible with the minimum required version.
-    Assumes versions in format "v0.0.0".
+
+    Args:
+        version: Version string in format "vX.Y.Z"
+        min_required_version: Minimum required version string in format "vX.Y.Z"
+
+    Returns:
+        bool: True if version is compatible (greater or equal), False otherwise
     """
     return extract_version_tuple(version) >= extract_version_tuple(min_required_version)
husarion_ugv_bringup/launch/bringup.launch.py (2)

45-45: Consider moving MIN_REQUIRED_OS_VERSION to a central configuration.

The version constant should be in a central configuration file to maintain consistency across the codebase.

Consider moving it to a new file like husarion_ugv_utils/config.py:

# husarion_ugv_utils/config.py
MIN_REQUIRED_OS_VERSION = "v2.2.0"

169-172: Consider alternative error handling approach.

The current approach of using sleep infinity to prevent exit might not be the best way to handle incorrect hardware configuration:

  1. It keeps the process running unnecessarily
  2. It might mask other issues
  3. It makes it harder to automate error handling

Consider these alternatives:

  1. Exit with a non-zero status code when exit_on_wrong_hw is true
  2. Implement a retry mechanism with backoff
  3. Add proper logging for monitoring and alerting

Also applies to: 174-180

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 40d595b and d1e7693.

📒 Files selected for processing (2)
  • husarion_ugv_bringup/launch/bringup.launch.py (3 hunks)
  • husarion_ugv_utils/husarion_ugv_utils/version_check.py (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Run unit tests hardware build type
  • GitHub Check: Run unit tests simulation build type
🔇 Additional comments (2)
husarion_ugv_bringup/launch/bringup.launch.py (2)

182-185: Simplify OS version check implementation.

Based on the past review comments, PythonExpression is only needed for UnlessCondition. The version check can be simplified.

-    os_version = os.environ.get("SYSTEM_BUILD_VERSION", "v0.0.0")
-    os_version_correct = PythonExpression(
-        f"{check_version_compatibility(os_version, MIN_REQUIRED_OS_VERSION)}"
-    )
+    os_version = EnvironmentVariable("SYSTEM_BUILD_VERSION", default_value="v0.0.0")
+    os_version_correct = PythonExpression(
+        [
+            "str('",
+            os_version,
+            "') >= '",
+            MIN_REQUIRED_OS_VERSION,
+            "'",
+        ]
+    )

167-167: Verify the default value for hardware configuration.

The default value "false" for ROBOT_HW_CONFIG_CORRECT means the driver won't start by default. This might not be the desired behavior for development or testing environments.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Description: Check if there are any environment setup files that might override this default.

# Search for environment setup files
fd -e 'sh' -e 'bash' -e 'env' | xargs grep -l "ROBOT_HW_CONFIG_CORRECT"

Length of output: 65


🏁 Script executed:

#!/bin/bash
# Search for all occurrences of "ROBOT_HW_CONFIG_CORRECT" in the codebase to check for any additional references or overrides.
rg "ROBOT_HW_CONFIG_CORRECT" -n .

Length of output: 184


Confirmed: The default value remains "false".

I searched the entire repository for any alternative settings or overrides for the ROBOT_HW_CONFIG_CORRECT variable and found only the instance in the file husarion_ugv_bringup/launch/bringup.launch.py. This confirms that the default remains set to "false", which means the driver will not start by default. If this behavior is not desired in development or testing environments, you may need to update the default value accordingly.

@rafal-gorecki rafal-gorecki merged commit d931eb3 into ros2-devel Feb 10, 2025
3 checks passed
@rafal-gorecki rafal-gorecki deleted the ros2-hw-and-os-check branch February 10, 2025 08:47
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.

2 participants