-
Notifications
You must be signed in to change notification settings - Fork 18
feat(#76): add basic FaultManager node with in-memory storage #86
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
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ../../src/ros2_medkit_fault_manager/design |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| # Copyright 2025 mfaferek93 | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| cmake_minimum_required(VERSION 3.8) | ||
| project(ros2_medkit_fault_manager) | ||
|
|
||
| set(CMAKE_CXX_STANDARD 23) | ||
| set(CMAKE_CXX_STANDARD_REQUIRED ON) | ||
| set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | ||
|
|
||
| if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") | ||
| add_compile_options(-Wall -Wextra -Wpedantic -Wshadow -Wconversion) | ||
| endif() | ||
|
|
||
| # Code coverage option | ||
| option(ENABLE_COVERAGE "Enable code coverage reporting" OFF) | ||
| if(ENABLE_COVERAGE) | ||
| message(STATUS "Code coverage enabled") | ||
| add_compile_options(--coverage -O0 -g) | ||
| add_link_options(--coverage) | ||
| endif() | ||
|
|
||
| find_package(ament_cmake REQUIRED) | ||
| find_package(rclcpp REQUIRED) | ||
| find_package(ros2_medkit_msgs REQUIRED) | ||
|
|
||
| # Library target (shared between executable and tests) | ||
| add_library(fault_manager_lib STATIC | ||
| src/fault_manager_node.cpp | ||
| src/fault_storage.cpp | ||
| ) | ||
|
|
||
| target_include_directories(fault_manager_lib PUBLIC | ||
| $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> | ||
| $<INSTALL_INTERFACE:include> | ||
| ) | ||
|
|
||
| ament_target_dependencies(fault_manager_lib | ||
| rclcpp | ||
| ros2_medkit_msgs | ||
| ) | ||
|
|
||
| if(ENABLE_COVERAGE) | ||
| target_compile_options(fault_manager_lib PRIVATE --coverage -O0 -g) | ||
| target_link_options(fault_manager_lib PRIVATE --coverage) | ||
| endif() | ||
|
|
||
| # Executable target | ||
| add_executable(fault_manager_node src/main.cpp) | ||
| target_link_libraries(fault_manager_node fault_manager_lib) | ||
|
|
||
| # Apply coverage flags to executable | ||
| if(ENABLE_COVERAGE) | ||
| target_compile_options(fault_manager_node PRIVATE --coverage -O0 -g) | ||
| target_link_options(fault_manager_node PRIVATE --coverage) | ||
| endif() | ||
|
|
||
| # Install targets | ||
| install(TARGETS fault_manager_node | ||
| DESTINATION lib/${PROJECT_NAME} | ||
| ) | ||
|
|
||
| install(DIRECTORY include/ | ||
| DESTINATION include | ||
| ) | ||
|
|
||
mfaferek93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| install(DIRECTORY launch | ||
| DESTINATION share/${PROJECT_NAME} | ||
| ) | ||
|
|
||
| # Testing | ||
| if(BUILD_TESTING) | ||
| find_package(ament_lint_auto REQUIRED) | ||
| find_package(ament_cmake_gtest REQUIRED) | ||
| find_package(launch_testing_ament_cmake REQUIRED) | ||
|
|
||
| set(ament_cmake_clang_format_CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../../.clang-format") | ||
| set(ament_cmake_clang_tidy_CONFIG_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../../.clang-tidy") | ||
| list(APPEND AMENT_LINT_AUTO_EXCLUDE ament_cmake_uncrustify ament_cmake_cpplint) | ||
| ament_lint_auto_find_test_dependencies() | ||
|
|
||
| # Unit tests | ||
| ament_add_gtest(test_fault_manager test/test_fault_manager.cpp) | ||
| target_link_libraries(test_fault_manager fault_manager_lib) | ||
| ament_target_dependencies(test_fault_manager rclcpp ros2_medkit_msgs) | ||
|
|
||
| # Apply coverage flags to test target | ||
| if(ENABLE_COVERAGE) | ||
| target_compile_options(test_fault_manager PRIVATE --coverage -O0 -g) | ||
| target_link_options(test_fault_manager PRIVATE --coverage) | ||
| endif() | ||
|
|
||
| # Integration tests | ||
| install(DIRECTORY test | ||
| DESTINATION share/${PROJECT_NAME} | ||
| ) | ||
|
|
||
| add_launch_test( | ||
| test/test_integration.test.py | ||
| TARGET test_integration | ||
| TIMEOUT 60 | ||
| ) | ||
| endif() | ||
|
|
||
| ament_package() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| # ros2_medkit_fault_manager | ||
|
|
||
| Central fault manager node for the ros2_medkit fault management system. | ||
|
|
||
| ## Overview | ||
|
|
||
| The FaultManager node provides a central point for fault aggregation and lifecycle management. | ||
| It receives fault reports from multiple sources, aggregates them by `fault_code`, and provides | ||
| query and clearing interfaces. | ||
|
|
||
| ## Services | ||
|
|
||
| | Service | Type | Description | | ||
| |---------|------|-------------| | ||
| | `~/report_fault` | `ros2_medkit_msgs/srv/ReportFault` | Report a fault occurrence | | ||
| | `~/get_faults` | `ros2_medkit_msgs/srv/GetFaults` | Query faults with filtering | | ||
| | `~/clear_fault` | `ros2_medkit_msgs/srv/ClearFault` | Clear/acknowledge a fault | | ||
|
|
||
| ## Features | ||
|
|
||
| - **Multi-source aggregation**: Same `fault_code` from different sources creates a single fault | ||
| - **Occurrence tracking**: Counts total reports and tracks all reporting sources | ||
| - **Severity escalation**: Fault severity is updated if a higher severity is reported | ||
| - **Status lifecycle**: PENDING → CONFIRMED → CLEARED (automatic status transitions in Issue #6) | ||
|
|
||
| ## Usage | ||
|
|
||
| ### Launch | ||
|
|
||
| ```bash | ||
| ros2 launch ros2_medkit_fault_manager fault_manager.launch.py | ||
| ``` | ||
|
|
||
| ### Manual Testing | ||
|
|
||
| ```bash | ||
| # Report a fault | ||
| ros2 service call /fault_manager/report_fault ros2_medkit_msgs/srv/ReportFault \ | ||
| "{fault_code: 'MOTOR_OVERHEAT', severity: 2, description: 'Motor temp exceeded', source_id: '/motor_node'}" | ||
|
|
||
| # Get all faults (including PENDING) | ||
| ros2 service call /fault_manager/get_faults ros2_medkit_msgs/srv/GetFaults \ | ||
| "{filter_by_severity: false, severity: 0, statuses: ['PENDING', 'CONFIRMED']}" | ||
|
|
||
| # Clear a fault | ||
| ros2 service call /fault_manager/clear_fault ros2_medkit_msgs/srv/ClearFault \ | ||
| "{fault_code: 'MOTOR_OVERHEAT'}" | ||
| ``` | ||
|
|
||
| ## Building | ||
|
|
||
| ```bash | ||
| colcon build --packages-select ros2_medkit_fault_manager | ||
| source install/setup.bash | ||
| ``` | ||
|
|
||
| ## Testing | ||
|
|
||
| ```bash | ||
| colcon test --packages-select ros2_medkit_fault_manager | ||
| colcon test-result --verbose | ||
| ``` | ||
|
|
||
| ## License | ||
|
|
||
| Apache-2.0 | ||
mfaferek93 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| @startuml ros2_medkit_fault_manager_architecture | ||
|
|
||
| skinparam linetype ortho | ||
| skinparam classAttributeIconSize 0 | ||
|
|
||
| title ROS 2 Medkit Fault Manager - Class Architecture | ||
|
|
||
| package "ROS 2 Framework" { | ||
| class "rclcpp::Node" { | ||
| +create_service() | ||
| +get_logger() | ||
| +now() | ||
| } | ||
| } | ||
|
|
||
| package "ros2_medkit_msgs" { | ||
| class "msg::Fault" { | ||
| +fault_code: string | ||
| +severity: uint8 | ||
| +description: string | ||
| +first_occurred: Time | ||
| +last_occurred: Time | ||
| +occurrence_count: uint32 | ||
| +status: string | ||
| +reporting_sources: string[] | ||
| } | ||
|
|
||
| class "srv::ReportFault" { | ||
| +Request: fault_code, severity, description, source_id | ||
| +Response: success, message | ||
| } | ||
|
|
||
| class "srv::GetFaults" { | ||
| +Request: filter_by_severity, severity, statuses | ||
| +Response: faults[] | ||
| } | ||
|
|
||
| class "srv::ClearFault" { | ||
| +Request: fault_code | ||
| +Response: success, message | ||
| } | ||
| } | ||
|
|
||
| package "ros2_medkit_fault_manager" { | ||
|
|
||
| class FaultManagerNode { | ||
| + get_storage(): FaultStorage& | ||
| } | ||
|
|
||
| abstract class FaultStorage <<interface>> { | ||
| + {abstract} report_fault(): bool | ||
| + {abstract} get_faults(): vector<Fault> | ||
| + {abstract} get_fault(): optional<Fault> | ||
| + {abstract} clear_fault(): bool | ||
| + {abstract} size(): size_t | ||
| + {abstract} contains(): bool | ||
| } | ||
|
|
||
| class InMemoryFaultStorage { | ||
| + report_fault(): bool | ||
| + get_faults(): vector<Fault> | ||
| + get_fault(): optional<Fault> | ||
| + clear_fault(): bool | ||
| + size(): size_t | ||
| + contains(): bool | ||
| } | ||
|
|
||
| class FaultState <<struct>> { | ||
| + to_msg(): Fault | ||
| } | ||
| } | ||
|
|
||
| ' Relationships | ||
|
|
||
| ' Inheritance | ||
| FaultManagerNode -up-|> "rclcpp::Node" : extends | ||
| InMemoryFaultStorage -up-|> FaultStorage : implements | ||
|
|
||
| ' Composition | ||
| FaultManagerNode *-down-> InMemoryFaultStorage : owns | ||
|
|
||
| ' InMemoryFaultStorage contains FaultStates | ||
| InMemoryFaultStorage o-right-> FaultState : contains many | ||
|
|
||
| ' FaultState converts to message | ||
| FaultState ..> "msg::Fault" : converts to | ||
|
|
||
| ' Node uses service types | ||
| FaultManagerNode ..> "srv::ReportFault" : handles | ||
| FaultManagerNode ..> "srv::GetFaults" : handles | ||
| FaultManagerNode ..> "srv::ClearFault" : handles | ||
|
|
||
| @enduml |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.