diff --git a/.docs/panther_ros2_api.drawio.svg b/.docs/panther_ros2_api.drawio.svg deleted file mode 100644 index 29cefa8b..00000000 --- a/.docs/panther_ros2_api.drawio.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -panther_localizationpanther_localizationpanther_controllerpanther_controllerpanther_lightspanther_lightspanther_hardware_interfacespanther_hardware_interfacespanther_batterypanther_batterypanther_managerpanther_managerpanther_diagnosticspanther_diagnosticsPantherSystemPantherSystemhardware_controllerhardware_controllerGPIOControllerGPIOControllerMotorsControllerMotorsControllerCANopenControllerCANopenControllerRoboteqDriverRoboteqDriverCANCANEStopManagerEStopManagerbattery_driverbattery_driverRPi GPIORPi GPIOADCADCimu_broadcasterimu_broadcasterjoint_state_broadcasterjoint_state_broadcasterdrive_controllerdrive_controllercontroller_managercontroller_managerPantherImuSensorPantherImuSensor IMUIMUekf_filterekf_filterImuFilterImuFilterSpatialSpatialimu/dataimu/dataodometry/wheelsodometry/wheelsodometry/filteredodometry/filteredjoint_statesjoint_statescmd_velcmd_veldynamic_joint_statesdynamic_joint_states hardware/e_stop hardware/e_stophardware/motor_controllers_statehardware/motor_controllers_state hardware/io_state hardware/io_statehardware/e_stop_triggerhardware/e_stop_triggerhardware/e_stop_resethardware/e_stop_resethardware/<hw_component>_enablehardware/<hw_component>_enablerobot_state_publisherrobot_state_publisherrobot_descriptionrobot_description/tf/tf/tf_static/tf_static/tf/tfbattery/battery_statusbattery/battery_statusBumper LightsBumper Lights lights_driverlights_driverlights_controllerlights_controllerlights/channel_1_framelights/channel_1_framelights/channel_2_framelights/channel_2_framelights/set_animationlights/set_animationlights/set_brightnesslights/set_brightness safety_managersafety_managersystem_monitorsystem_monitorsystem_statussystem_statuslights_managerlights_managerhardware/led_control_enablehardware/led_control_enable/tf/tfbattery/charging_statusbattery/charging_statusGPIODriverGPIODriverdiagnosticsdiagnosticsdiagnosticsdiagnosticsdiagnosticsdiagnostics diagnosticsdiagnosticsLegend:Legend:NodesNodesPluginPluginObjectsObjectsTopicsTopicsServicesServicesData TransferData Trans...Text is not SVG - cannot display diff --git a/.docs/ros2_system_design.drawio.svg b/.docs/ros2_system_design.drawio.svg new file mode 100644 index 00000000..ef55b4d4 --- /dev/null +++ b/.docs/ros2_system_design.drawio.svg @@ -0,0 +1,4 @@ + + + +husarion_ugv_localizationhusarion_ugv_localizationhusarion_ugv_controllerhusarion_ugv_controllerhusarion_ugv_lightshusarion_ugv_lightshusarion_ugv_hardware_interfaceshusarion_ugv_hardware_interfaceshusarion_ugv_batteryhusarion_ugv_batteryhusarion_ugv_managerhusarion_ugv_managerhusarion_ugv_diagnosticshusarion_ugv_diagnostics{Robot}System{Robot}Systemhardware_controllerhardware_controllerGPIOControllerGPIOControllerMotorsControllerMotorsControllerCANopenControllerCANopenControllerRoboteqDriverRoboteqDriverCANCANEStopManagerEStopManagerbattery_driverbattery_driverRPi GPIORPi GPIOADCADCimu_broadcasterimu_broadcasterjoint_state_broadcasterjoint_state_broadcasterdrive_controllerdrive_controllercontroller_managercontroller_managerPhidgetImuSensorPhidgetImuSensor IMUIMUekf_filterekf_filterImuFilterImuFilterSpatialSpatialimu/dataimu/dataodometry/wheelsodometry/wheelsodometry/filteredodometry/filteredjoint_statesjoint_statescmd_velcmd_veldynamic_joint_statesdynamic_joint_states hardware/e_stop hardware/e_stophardware/robot_driver_statehardware/robot_driver_state hardware/io_state hardware/io_statehardware/e_stop_triggerhardware/e_stop_triggerhardware/e_stop_resethardware/e_stop_resethardware/<hw_component>_enablehardware/<hw_component>_enablerobot_state_publisherrobot_state_publisherrobot_descriptionrobot_description/tf/tf/tf_static/tf_static/tf/tfbattery/battery_statusbattery/battery_statusBumper LightsBumper Lights lights_driverlights_driverlights_controllerlights_controllerlights/channel_1_framelights/channel_1_framelights/channel_2_framelights/channel_2_framelights/set_animationlights/set_animationlights/set_brightnesslights/set_brightness safety_managersafety_managersystem_monitorsystem_monitorsystem_statussystem_statuslights_managerlights_managerhardware/led_control_enablehardware/led_control_enable/tf/tfbattery/charging_statusbattery/charging_statusGPIODriverGPIODriverdiagnosticsdiagnosticsdiagnosticsdiagnosticsdiagnosticsdiagnostics diagnosticsdiagnosticsLegend:Legend:NodesNodesPluginPluginObjectsObjectsTopicsTopicsServicesServicesData TransferData Trans...Text is not SVG - cannot display diff --git a/.github/workflows/release-candidate.yaml b/.github/workflows/release-candidate.yaml index c1504ad1..f2744f57 100644 --- a/.github/workflows/release-candidate.yaml +++ b/.github/workflows/release-candidate.yaml @@ -5,17 +5,31 @@ on: workflow_dispatch: inputs: version: - description: Release candidate version. IMPORTANT - required format `X.X.X`, eg `2.0.1`. + description: Release candidate version (format `X.X.X`, e.g. `2.0.1`). required: true date: - description: Release candidate date stamp. IMPORTANT - required format `YYYYMMDD`, eg `20240430`. + description: Release candidate date stamp (format `YYYYMMDD`, e.g. `20240430`). required: true env: RC_BRANCH_NAME: ${{ github.event.inputs.version }}-${{ github.event.inputs.date }} jobs: - # TODO: Add unit testing for panther_ros when ready + check_docs: + name: Check docs build + runs-on: ubuntu-22.04 + steps: + - name: Trigger repository build workflow + uses: convictional/trigger-workflow-and-wait@v1.6.1 + with: + owner: husarion + repo: docs_new + github_token: ${{ secrets.GH_PAT }} + workflow_file_name: test-release.yml + ref: master + client_payload: '{"husarion_ugv_branch": "ros2-devel"}' + + # TODO: Add unit testing for panther_ros when ready unit_test_panther_ros: name: Run unit tests for panther_ros runs-on: ubuntu-22.04 @@ -55,7 +69,6 @@ jobs: github_token: ${{ secrets.GH_PAT }} workflow_file_name: update-tags-in-compose.yaml ref: ${{ env.RC_BRANCH_NAME }} - wait_interval: 10 client_payload: | { "branch_name": "${{ env.RC_BRANCH_NAME }}", @@ -76,7 +89,6 @@ jobs: github_token: ${{ secrets.GH_PAT }} workflow_file_name: ros-docker-image.yaml ref: ${{ env.RC_BRANCH_NAME }} - wait_interval: 10 client_payload: | { "panther_codebase_version": "${{ env.RC_BRANCH_NAME }}", @@ -98,7 +110,6 @@ jobs: github_token: ${{ secrets.GH_PAT }} workflow_file_name: build_and_deploy_image.yaml ref: ${{ env.RC_BRANCH_NAME }} - wait_interval: 10 client_payload: | { "dev_image": "true", @@ -121,7 +132,6 @@ jobs: github_token: ${{ secrets.GH_PAT }} workflow_file_name: build_and_deploy_flash_os_image.yaml ref: ${{ env.RC_BRANCH_NAME }} - wait_interval: 10 client_payload: | { "image_tag": "${{ github.event.inputs.version }}" diff --git a/.github/workflows/release-project.yaml b/.github/workflows/release-project.yaml index 47800b4f..4ac40ef2 100644 --- a/.github/workflows/release-project.yaml +++ b/.github/workflows/release-project.yaml @@ -1,5 +1,5 @@ --- -name: Release Panther project +name: Release project on: workflow_dispatch: @@ -30,11 +30,11 @@ env: MAIN_BRANCH: ros2 jobs: - release_panther_msgs: - name: Release panther_msgs repository + release_project: + name: Release Husarion UGV project runs-on: ubuntu-22.04 steps: - - name: Trigger repository release workflow + - name: Release panther_msgs repository uses: convictional/trigger-workflow-and-wait@v1.6.1 with: owner: husarion @@ -42,7 +42,6 @@ jobs: github_token: ${{ secrets.GH_PAT }} workflow_file_name: release-repository.yaml ref: ${{ env.RC_BRANCH_NAME }} - wait_interval: 10 client_payload: | { "release_candidate": "${{ env.RC_BRANCH_NAME }}", @@ -52,13 +51,7 @@ jobs: "prerelease": "${{ github.event.inputs.prerelease }}" } - release_panther_ros: - name: Release panther_ros repository - needs: - - release_panther_msgs - runs-on: ubuntu-22.04 - steps: - - name: Trigger panther_ros release workflow + - name: Release panther_ros repository uses: convictional/trigger-workflow-and-wait@v1.6.1 with: owner: husarion @@ -66,7 +59,6 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} # Use the default GITHUB_TOKEN for local repository workflow_file_name: release-repository.yaml ref: ${{ env.RC_BRANCH_NAME }} - wait_interval: 10 client_payload: | { "release_candidate": "${{ env.RC_BRANCH_NAME }}", @@ -76,13 +68,7 @@ jobs: "prerelease": "${{ github.event.inputs.prerelease }}" } - rebuild_and_push_docker_images: - name: Rebuild panther docker images with new version - runs-on: ubuntu-22.04 - needs: - - release_panther_ros - steps: - - name: Trigger repository build workflow + - name: Rebuild panther docker images with new version uses: convictional/trigger-workflow-and-wait@v1.6.1 with: owner: husarion @@ -90,7 +76,6 @@ jobs: github_token: ${{ secrets.GH_PAT }} workflow_file_name: ros-docker-image.yaml ref: ${{ env.RC_BRANCH_NAME }} - wait_interval: 10 client_payload: | { "panther_codebase_version": "${{ github.event.inputs.version }}", @@ -98,13 +83,7 @@ jobs: "target_distro": "humble" } - release_panther_docker: - name: Release panther-docker repository - needs: - - rebuild_and_push_docker_images - runs-on: ubuntu-22.04 - steps: - - name: Trigger repository release workflow + - name: Release panther-docker repository uses: convictional/trigger-workflow-and-wait@v1.6.1 with: owner: husarion @@ -112,7 +91,6 @@ jobs: github_token: ${{ secrets.GH_PAT }} workflow_file_name: release-repository.yaml ref: ${{ env.RC_BRANCH_NAME }} - wait_interval: 10 client_payload: | { "release_candidate": "${{ env.RC_BRANCH_NAME }}", @@ -122,14 +100,7 @@ jobs: "prerelease": "${{ github.event.inputs.prerelease }}" } - release_panther_rpi_os_image: - name: Release panther-rpi-os-img repository - if: ${{ fromJSON(github.event.inputs.automatic_mode) == true }} - needs: - - release_panther_docker - runs-on: ubuntu-22.04 - steps: - - name: Trigger repository release workflow + - name: Release panther-rpi-os-img repository uses: convictional/trigger-workflow-and-wait@v1.6.1 with: owner: husarion @@ -137,7 +108,6 @@ jobs: github_token: ${{ secrets.GH_PAT }} workflow_file_name: release-repository.yaml ref: ${{ env.RC_BRANCH_NAME }} - wait_interval: 10 client_payload: | { "release_candidate": "${{ env.RC_BRANCH_NAME }}", @@ -147,14 +117,8 @@ jobs: "prerelease": "${{ github.event.inputs.prerelease }}" } - build_and_publish_rpi_image: - name: Build panther system image - if: ${{ fromJSON(github.event.inputs.automatic_mode) == true }} - needs: - - release_panther_rpi_os_image - runs-on: ubuntu-22.04 - steps: - - name: Trigger repository build workflow + - name: Build panther system image + if: ${{ fromJSON(github.event.inputs.automatic_mode) == true }} uses: convictional/trigger-workflow-and-wait@v1.6.1 with: owner: husarion @@ -162,7 +126,6 @@ jobs: github_token: ${{ secrets.GH_PAT }} workflow_file_name: build_and_deploy_image.yaml ref: ${{ env.MAIN_BRANCH }} - wait_interval: 10 client_payload: | { "dev_image": "false", @@ -170,14 +133,8 @@ jobs: "image_tag": "${{ github.event.inputs.version }}" } - build_and_publish_rpi_flash_os_image: - name: Build panther flash OS image - if: ${{ fromJSON(github.event.inputs.automatic_mode) == true }} - needs: - - build_and_publish_rpi_image - runs-on: ubuntu-22.04 - steps: - - name: Trigger repository build workflow + - name: Build panther flash OS image + if: ${{ fromJSON(github.event.inputs.automatic_mode) == true }} uses: convictional/trigger-workflow-and-wait@v1.6.1 with: owner: husarion @@ -185,8 +142,16 @@ jobs: github_token: ${{ secrets.GH_PAT }} workflow_file_name: build_and_deploy_flash_os_image.yaml ref: ${{ env.MAIN_BRANCH }} - wait_interval: 10 client_payload: | { "image_tag": "${{ github.event.inputs.version }}" } + + - name: Trigger repository build workflow + uses: convictional/trigger-workflow-and-wait@v1.6.1 + with: + owner: husarion + repo: docs_new + github_token: ${{ secrets.GH_PAT }} + workflow_file_name: build.yml + ref: master diff --git a/.github/workflows/run-unit-tests.yaml b/.github/workflows/run-unit-tests.yaml index 6d7d4878..48c1ebf6 100644 --- a/.github/workflows/run-unit-tests.yaml +++ b/.github/workflows/run-unit-tests.yaml @@ -1,5 +1,5 @@ --- -name: Run panther unit tests +name: Run unit tests on: workflow_dispatch: @@ -28,12 +28,12 @@ jobs: uses: actions/checkout@v3 with: ref: ${{ github.ref }} - path: ros2_ws/src/panther_ros + path: ros2_ws/src/husarion_ugv - name: Resolve dependencies working-directory: ros2_ws run: | - vcs import < src/panther_ros/panther/panther_hardware.repos src + vcs import < src/husarion_ugv/husarion_ugv/hardware_deps.repos src sudo apt update rosdep update --rosdistro $ROS_DISTRO rosdep install -i --from-path src --rosdistro $ROS_DISTRO -y @@ -43,15 +43,15 @@ jobs: run: | source /opt/ros/$ROS_DISTRO/setup.bash if [ -f install/setup.bash ]; then source install/setup.bash; fi - colcon build --symlink-install --parallel-workers $(nproc) --packages-up-to panther --cmake-args -DCMAKE_CXX_FLAGS='-fprofile-arcs -ftest-coverage' + colcon build --symlink-install --parallel-workers $(nproc) --packages-up-to husarion_ugv --cmake-args -DCMAKE_CXX_FLAGS='-fprofile-arcs -ftest-coverage' - name: Test working-directory: ros2_ws run: | source install/setup.bash - colcon test --packages-up-to panther --retest-until-pass 10 --event-handlers console_cohesion+ --return-code-on-test-failure + colcon test --packages-up-to husarion_ugv --retest-until-pass 10 --event-handlers console_cohesion+ --return-code-on-test-failure echo "result=$?" >> ${{ runner.temp }}/${{ env.TEST_RESULT_FILENAME }} - colcon lcov-result --packages-up-to panther --verbose >> ${{ runner.temp }}/${{ env.COVERAGE_RESULT_FILENAME }} + colcon lcov-result --packages-up-to husarion_ugv --verbose >> ${{ runner.temp }}/${{ env.COVERAGE_RESULT_FILENAME }} lines_cov=$(cat ${{ runner.temp }}/${{ env.COVERAGE_RESULT_FILENAME }} | grep -E 'lines' | head -1) functions_cov=$(cat ${{ runner.temp }}/${{ env.COVERAGE_RESULT_FILENAME }} | grep -E 'functions' | head -1) branches_cov=$(cat ${{ runner.temp }}/${{ env.COVERAGE_RESULT_FILENAME }} | grep -E 'branches' | head -1) diff --git a/.gitignore b/.gitignore index f42d579a..ac9f2a85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -devel/ -logs/ build/ +log/ +install/ bin/ lib/ msg_gen/ @@ -13,8 +13,6 @@ msg/*Feedback.msg msg/*Goal.msg msg/*Result.msg msg/_*.py -build_isolated/ -devel_isolated/ # Generated by dynamic reconfigure *.cfgc diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c426d210..a685e4f1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -47,7 +47,7 @@ repos: entry: codespell args: [ - "--exclude-file=panther_hardware_interfaces/config/roboteq_motor_controllers_v80_21a.eds", + "--exclude-file=husarion_ugv_hardware_interfaces/config/roboteq_motor_controllers_v80_21a.eds", "--ignore-words-list", "ned" # north, east, down (NED) ] diff --git a/README.md b/README.md index 633e44f3..63c8c9ab 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# panther_ros +# husarion_ugv -ROS 2 packages for Panther autonomous mobile robot +ROS 2 packages for Husarion UGV (Unmanned Ground Vehicle). The repository is a collection of necessary packages enabling the launch of the Lynx and Panther robots. [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit) @@ -16,7 +16,7 @@ ROS 2 packages for Panther autonomous mobile robot ```bash mkdir ~/husarion_ws cd ~/husarion_ws -git clone -b ros2 https://github.com/husarion/panther_ros.git src/panther_ros +git clone -b ros2 https://github.com/husarion/panther_ros.git src/husarion_ugv ``` ### Configure environment @@ -38,7 +38,7 @@ export HUSARION_ROS_BUILD_TYPE=simulation ### Build ``` bash -vcs import src < src/panther_ros/panther/panther_$HUSARION_ROS_BUILD_TYPE.repos +vcs import src < src/husarion_ugv/husarion_ugv/${HUSARION_ROS_BUILD_TYPE}_deps.repos cp -r src/ros2_controllers/diff_drive_controller src cp -r src/ros2_controllers/imu_sensor_broadcaster src @@ -49,28 +49,31 @@ rosdep update --rosdistro $ROS_DISTRO rosdep install --from-paths src -y -i source /opt/ros/$ROS_DISTRO/setup.bash -colcon build --symlink-install --packages-up-to panther --cmake-args -DCMAKE_BUILD_TYPE=Release +colcon build --symlink-install --packages-up-to husarion_ugv --cmake-args -DCMAKE_BUILD_TYPE=Release source install/setup.bash ``` >[!NOTE] -> To build code on a real robot you need to run above commands on the Panther Built-in Computer. +> To build code on a real robot you need to run above commands on the robot Built-in Computer. ### Running Real robot: ```bash -ros2 launch panther_bringup bringup.launch.py +ros2 launch husarion_ugv_bringup bringup.launch.py ``` Simulation: ```bash -ros2 launch panther_gazebo simulation.launch.py +ros2 launch husarion_ugv_gazebo simulation.launch.py ``` +> [!IMPORTANT] +> You can change spawning robot in simulation, by adding `robot_model:={robot_model}` argument. + ### Launch Arguments Launch arguments are largely common to both simulation and physical robot. However, there is a group of arguments that apply only to hardware or only to the simulator. Below is a legend to the tables with all launch arguments. @@ -80,45 +83,46 @@ Launch arguments are largely common to both simulation and physical robot. Howev | 🤖 | Available for physical robot | | 🖥️ | Available in simulation | -| | Argument | Description ***Type:*** `Default` | -| --- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 🖥️ | `add_wheel_joints` | Flag enabling joint_state_publisher to publish information about the wheel position. Should be false when there is a controller that sends this information. ***bool:*** `False` | -| 🖥️ | `add_world_transform` | Adds a world frame that connects the tf trees of individual robots (useful when running multiple robots). ***bool:*** `False` | -| 🖥️ | `battery_config_path` | Path to the Ignition LinearBatteryPlugin configuration file. This configuration is intended for use in simulations only. ***string:*** `None` | -| 🤖🖥️ | `components_config_path` | Additional components configuration file. Components described in this file are dynamically included in Panther's urdf. Panther options are described in [the manual](https://husarion.com/manuals/panther/panther-options). ***string:*** [`components.yaml`](./panther_description/config/components.yaml) | -| 🤖🖥️ | `controller_config_path` | Path to controller configuration file. A path to custom configuration can be specified here. ***string:*** [`{wheel_type}_controller.yaml`](./panther_controller/config/) | -| 🤖 | `disable_manager` | Enable or disable manager_bt_node. ***bool:*** `False` | -| 🤖🖥️ | `fuse_gps` | Include GPS for data fusion. ***bool:*** `False` | -| 🖥️ | `gz_bridge_config_path` | Path to the parameter_bridge configuration file. ***string:*** [`gz_bridge.yaml`](./panther_gazebo/config/gz_bridge.yaml) | -| 🖥️ | `gz_gui` | Run simulation with specific GUI layout. ***string:*** [`teleop.config`](https://github.com/husarion/husarion_gz_worlds/blob/main/config/teleop.config) | -| 🖥️ | `gz_headless_mode` | Run the simulation in headless mode. Useful when a GUI is not needed or to reduce the number of calculations. ***bool:*** `False` | -| 🖥️ | `gz_log_level` | Adjust the level of console output. ***int:*** `1` (choices: `0`, `1`, `2`, `3`, `4`) | -| 🖥️ | `gz_world` | Absolute path to SDF world file. ***string:*** [`husarion_world.sdf`](https://github.com/husarion/husarion_gz_worlds/blob/main/worlds/husarion_world.sdf) | -| 🤖 | `launch_nmea_gps` | Whether to launch the NMEA NavSat driver node. Advisable when the robot is equipped with the [ANT02](https://husarion.com/manuals/panther/panther-options/#ant02---wi-fi--lte--gps). ***bool:*** `False` | -| 🤖🖥️ | `led_config_file` | Path to a YAML file with a description of led configuration. This file includes definition of robot panels, virtual segments and default animations. ***string:*** [`led_config.yaml`](./panther_lights/config/led_config.yaml) | -| 🤖🖥️ | `lights_bt_project_path` | Path to BehaviorTree project file, responsible for lights management. ***string:*** [`PantherLightsBT.btproj`](./panther_manager/behavior_trees/PantherLightsBT.btproj) | -| 🤖🖥️ | `localization_config_path` | Specify the path to the localization configuration file. ***string:*** [`relative_localization.yaml`](./panther_localization/config/relative_localization.yaml) | -| 🤖🖥️ | `localization_mode` | Specifies the localization mode: - 'relative' `odometry/filtered` data is relative to the initial position and orientation. - 'enu' `odometry/filtered` data is relative to initial position and ENU (East North Up) orientation. ***string:*** `relative` (choices: `relative`, `enu`) | -| 🤖🖥️ | `namespace` | Add namespace to all launched nodes. ***string:*** `env(ROBOT_NAMESPACE)` | -| 🤖🖥️ | `publish_robot_state` | Whether to publish the default Panther robot description. ***bool:*** `True` | -| 🖥️ | `robots` | The list of the robots spawned in the simulation e.g. `robots:='robot1={x: 1.0, y: -2.0}; robot2={x: 1.0, y: -4.0}'` ***string:*** `''` | -| 🤖🖥️ | `safety_bt_project_path` | Path to BehaviorTree project file, responsible for safety and shutdown management. ***string:*** [`PantherSafetyBT.btproj`](./panther_manager/behavior_trees/PantherSafetyBT.btproj) | -| 🤖🖥️ | `shutdown_hosts_config_path` | Path to file with list of hosts to request shutdown. ***string:*** [`shutdown_hosts_config.yaml`](./panther_manager/config/shutdown_hosts_config.yaml) | -| 🤖🖥️ | `use_ekf` | Enable or disable EKF. ***bool:*** `True` | -| 🤖🖥️ | `use_sim` | Whether simulation is used. ***bool:*** `False` | -| 🤖🖥️ | `user_led_animations_file` | Path to a YAML file with a description of the user-defined animations. ***string:*** `''` | -| 🤖🖥️ | `wheel_config_path` | Path to wheel configuration file. ***string:*** [`{wheel_type}.yaml`](./panther_description/config) | -| 🤖🖥️ | `wheel_type` | Type of wheel. If you choose a value from the preset options ('WH01', 'WH02', 'WH04'), you can ignore the 'wheel_config_path' and 'controller_config_path' parameters. For custom wheels, please define these parameters to point to files that accurately describe the custom wheels. ***string:*** `WH01` (choices: `WH01`, `WH02`, `WH04`, `custom`) | -| 🖥️ | `x` | Initial robot position in the global 'x' axis. ***float:*** `0.0` | -| 🖥️ | `y` | Initial robot position in the global 'y' axis. ***float:***` -2.0` | -| 🖥️ | `z` | Initial robot position in the global 'z' axis. ***float:*** `0.2` | -| 🖥️ | `roll` | Initial robot 'roll' orientation. ***float:*** `0.0` | -| 🖥️ | `pitch` | Initial robot 'pitch' orientation. ***float:*** `0.0` | -| 🖥️ | `yaw` | Initial robot 'yaw' orientation. ***float:*** `0.0` | +| 🤖 | 🖥️ | Argument | Description ***Type:*** `Default` | +| --- | --- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| ❌ | ✅ | `add_wheel_joints` | Flag enabling joint_state_publisher to publish information about the wheel position. Should be false when there is a controller that sends this information. ***bool:*** `False` | +| ❌ | ✅ | `add_world_transform` | Adds a world frame that connects the tf trees of individual robots (useful when running multiple robots). ***bool:*** `False` | +| ✅ | ✅ | `animations_config_path` | Path to a YAML file with a description of led configuration. This file includes definition of robot panels, virtual segments and default animations. ***string:*** [`{robot_model}_animations.yaml`](./husarion_ugv_lights/config) | +| ❌ | ✅ | `battery_config_path` | Path to the Ignition LinearBatteryPlugin configuration file. This configuration is intended for use in simulations only. ***string:*** `None` | +| ✅ | ✅ | `components_config_path` | Additional components configuration file. Components described in this file are dynamically included in robot's URDF. Available options are described in [the manual](https://husarion.com/manuals/panther/panther-options). ***string:*** [`components.yaml`](./panther_description/config/components.yaml) | +| ✅ | ✅ | `controller_config_path` | Path to controller configuration file. A path to custom configuration can be specified here. ***string:*** [`{wheel_type}_controller.yaml`](./husarion_ugv_controller/config/) | +| ✅ | ✅ | `disable_manager` | Enable or disable manager_bt_node. ***bool:*** `False` | +| ✅ | ✅ | `fuse_gps` | Include GPS for data fusion. ***bool:*** `False` | +| ❌ | ✅ | `gz_bridge_config_path` | Path to the parameter_bridge configuration file. ***string:*** [`gz_bridge.yaml`](./husarion_ugv_gazebo/config/gz_bridge.yaml) | +| ❌ | ✅ | `gz_gui` | Run simulation with specific GUI layout. ***string:*** [`teleop.config`](https://github.com/husarion/husarion_gz_worlds/blob/main/config/teleop.config) | +| ❌ | ✅ | `gz_headless_mode` | Run the simulation in headless mode. Useful when a GUI is not needed or to reduce the number of calculations. ***bool:*** `False` | +| ❌ | ✅ | `gz_log_level` | Adjust the level of console output. ***int:*** `1` (choices: `0`, `1`, `2`, `3`, `4`) | +| ❌ | ✅ | `gz_world` | Absolute path to SDF world file. ***string:*** [`husarion_world.sdf`](https://github.com/husarion/husarion_gz_worlds/blob/main/worlds/husarion_world.sdf) | +| ✅ | ✅ | `launch_nmea_gps` | Whether to launch the NMEA NavSat driver node. Advisable when the robot is equipped with the [ANT02](https://husarion.com/manuals/panther/panther-options/#ant02---wi-fi--lte--gps). ***bool:*** `False` | +| ✅ | ✅ | `lights_bt_project_path` | Path to BehaviorTree project file, responsible for lights management. ***string:*** [`LightsBT.btproj`](./husarion_ugv_manager/behavior_trees/LightsBT.btproj) | +| ✅ | ✅ | `localization_config_path` | Specify the path to the localization configuration file. ***string:*** [`relative_localization.yaml`](./husarion_ugv_localization/config/relative_localization.yaml) | +| ✅ | ✅ | `localization_mode` | Specifies the localization mode: - 'relative' `odometry/filtered` data is relative to the initial position and orientation. - 'enu' `odometry/filtered` data is relative to initial position and ENU (East North Up) orientation. ***string:*** `relative` (choices: `relative`, `enu`) | +| ✅ | ✅ | `namespace` | Add namespace to all launched nodes. ***string:*** `env(ROBOT_NAMESPACE)` | +| ✅ | ✅ | `publish_robot_state` | Whether to publish the default URDF of specified robot. ***bool:*** `True` | +| ❌ | ✅ | `robot_model` | Specify robot model type. ***string:*** `env(ROBOT_MODEL_NAME)` (choices: `lynx`, `panther`) | +| ✅ | ✅ | `safety_bt_project_path` | Path to BehaviorTree project file, responsible for safety and shutdown management. ***string:*** [`SafetyBT.btproj`](./husarion_ugv_manager/behavior_trees/SafetyBT.btproj) | +| ✅ | ✅ | `shutdown_hosts_config_path` | Path to file with list of hosts to request shutdown. ***string:*** [`shutdown_hosts.yaml`](./husarion_ugv_manager/config/shutdown_hosts.yaml) | +| ✅ | ✅ | `use_ekf` | Enable or disable EKF. ***bool:*** `True` | +| ❌ | ✅ | `use_rviz` | Run RViz simultaneously. ***bool:*** `True` | +| ✅ | ✅ | `use_sim` | Whether simulation is used. ***bool:*** `False` | +| ✅ | ✅ | `user_led_animations_path` | Path to a YAML file with a description of the user-defined animations. ***string:*** `''` | +| ✅ | ✅ | `wheel_config_path` | Path to wheel configuration file. ***string:*** [`{wheel_type}.yaml`](./panther_description/config) | +| ✅ | ✅ | `wheel_type` | Specify the wheel type. If the selected wheel type is not 'custom', the wheel_config_path and controller_config_path arguments will be automatically adjusted and can be omitted. ***string:*** `WH01` (for Panther), `WH05` (for Lynx) (choices: `WH01`, `WH02`, `WH04`, `WH05`, `custom`) | +| ❌ | ✅ | `x` | Initial robot position in the global 'x' axis. ***float:*** `0.0` | +| ❌ | ✅ | `y` | Initial robot position in the global 'y' axis. ***float:***` -2.0` | +| ❌ | ✅ | `z` | Initial robot position in the global 'z' axis. ***float:*** `0.0` | +| ❌ | ✅ | `roll` | Initial robot 'roll' orientation. ***float:*** `0.0` | +| ❌ | ✅ | `pitch` | Initial robot 'pitch' orientation. ***float:*** `0.0` | +| ❌ | ✅ | `yaw` | Initial robot 'yaw' orientation. ***float:*** `0.0` | > [!TIP] > -> To read the arguments for individual packages, add the `-s` flag to the `ros2 launch` command (e.g. `ros2 launch panther_bringup bringup.launch.py -s`) +> To read the arguments for individual packages, add the `-s` flag to the `ros2 launch` command (e.g. `ros2 launch husarion_ugv_bringup bringup.launch.py -s`) ## Developer Info diff --git a/ROS_API.md b/ROS_API.md index 1a92bdc2..f29c0664 100644 --- a/ROS_API.md +++ b/ROS_API.md @@ -3,9 +3,9 @@ > [!IMPORTANT] > **Beta Release** > -> Please be advised that the software you are about to use is a Beta version of the ROS 2 Driver for Panther. It is functional, and the architecture will not change significantly. Although it has been tested by the Husarion team, some stability issues and bugs may still occur. +> Please be advised that the software you are about to use is a Beta version of the ROS 2 Driver for Lynx and Panther. It is functional, and the architecture will not change significantly. Although it has been tested by the Husarion team, some stability issues and bugs may still occur. > -> We would greatly appreciate your feedback regarding the Panther ROS 2 driver. You can reach us in the following ways: +> We would greatly appreciate your feedback regarding the Husarion UGV ROS 2 driver. You can reach us in the following ways: > > - By email at: [support@husarion.com](mailto:support@husarion.com) > - Via our community forum: [Husarion Community](https://community.husarion.com) @@ -13,20 +13,20 @@ ## ROS 2 System Design -This section describes the ROS packages in the Panther ROS system. These packages are located in the [panther_ros](https://github.com/husarion/panther_ros) GitHub repository. +This section describes the ROS packages used in Husarion UGV. These packages are located in the [panther_ros](https://github.com/husarion/panther_ros) GitHub repository. > [!NOTE] -> **Differences in ROS System** +> **Hardware Compatibility** > -> ROS 2 nodes differs slightly between **Panther v1.06** and **Panther v1.2+**. This is caused by internal hardware differences. Despite that, the ROS API was kept as closely matched between those revisions as possible and should be transparent in most of the use cases. +> This package supports **Lynx v0.2+**, **Panther v1.2+**. There may be small differences between robot models. This is caused by the hardware differences. Despite that, the ROS API was kept as closely matched between those revisions as possible and should be transparent in most of the use cases. -The default way to communicate with Panther's hardware is via the Robot Operating System (ROS). All the drivers were written in ROS 2 framework. The ROS API is provided by ROS packages found in the GitHub repository [husarion/panther_ros](https://github.com/husarion/panther_ros). These packages are responsible for accessing the hardware components of the robot. +The default way to communicate with our robots is via the Robot Operating System (ROS). All the drivers were written in ROS 2 framework. The ROS API is provided by ROS packages found in the GitHub repository [husarion/panther_ros](https://github.com/husarion/panther_ros). These packages are responsible for accessing the hardware components of the robot. -The graph below represents Panther's ROS system. Some topics and services have been excluded from the graph for the sake of clarity. +The graph below represents Husarion UVG ROS system. Some topics and services have been excluded from the graph for the sake of clarity. -![Panther ROS 2 API Diagram](.docs/panther_ros2_api.drawio.svg) +![Husarion UVG ROS 2 System Design Diagram](.docs/ros2_system_design.drawio.svg) ## ROS Interfaces @@ -37,91 +37,92 @@ Below is information about the physical robot API. For the simulation, topics an | 🤖 | Available for physical robot | | 🖥️ | Available in simulation | | ⚙️ | Requires specific configuration | + ### Nodes -| | Node name | Description | -| --- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 🤖 | `battery_driver` | Publishes battery state read from ADC unit for Panther version 1.2 and above, or based on Roboteq motor controllers' data for earlier versions of the robot. [*panther_batter/battery_driver_node*](./panther_battery/include/panther_battery/battery_driver_node.hpp) | -| 🤖🖥️ | `controller_manager` | The Controller Manager performs two main functions. First, it manages controllers and their required interfaces, handling tasks like loading, activating, deactivating, and unloading. Second, it interacts with hardware components, ensuring access to their interfaces. This node manages the: `imu_broadcaster`, `joint_state_broadcaster`, `drive_controller`. *[controller_manager/controller_manager](https://github.com/ros-controls/ros2_control/blob/master/controller_manager)* | -| 🤖🖥️ | `drive_controller` | Manages mobile robots with a differential or mecanum drive depending on the configuration. It converts velocity commands for the robot body into wheel commands for the base. It also calculates odometry from hardware feedback and shares it. *[diff_drive_controller/diff_drive_controller](https://github.com/ros-controls/ros2_controllers/tree/master/diff_drive_controller) or [mecanum_drive_controller/mecanum_drive_controller](https://github.com/husarion/husarion_controllers/tree/main/mecanum_drive_controller)* | -| 🤖🖥️ | `ekf_filter` | The Extended Kalman Filter node is designed to fuse odometry data from various sources, including wheel encoders, IMU, and GPS. *[robot_localization/ekf_filter](https://github.com/cra-ros-pkg/robot_localization)* | -| 🤖 | `hardware_controller` | Plugin responsible for communicating with engine controllers via the CAN bus and providing E-Stop functionalities. *[panther_hardware_interfaces/PantherSystem](./panther_hardware_interfaces/src/panther_system/)* | -| 🤖 | `gps` | Node responsible for parsing NMEA strings and publishing standard ROS NavSat message types. *[nmea_navsat_driver/nmea_navsat_driver](https://github.com/ros-drivers/nmea_navsat_driver/tree/ros2/src/libnmea_navsat_driver)* | -| 🖥️ | `gz_ros2_control` | Responsible for integrating the ros2_control controller architecture with the Gazebo simulator. [gz_ros2_control/gz_ros2_control](https://github.com/ros-controls/gz_ros2_control/tree/master/gz_ros2_control/src) | -| 🖥️ | `gz_estop_gui` | The node is part of the Gazebo GUI plugin, enabling easy E-stop state modifications directly within the simulation. [panther_gazebo/EStop](./panther_gazebo/src/gui/e_stop.cpp) | -| 🤖🖥️ | `imu_broadcaster` | Publishes readings of IMU sensors. *[imu_sensor_broadcaster/imu_sensor_broadcaster](https://github.com/ros-controls/ros2_controllers/tree/master/imu_sensor_broadcaster)* | -| 🤖🖥️ | `joint_state_broadcaster` | Reads all state interfaces and reports them on specific topics. *[joint_state_broadcaster/joint_state_broadcaster](https://github.com/ros-controls/ros2_controllers/tree/master/joint_state_broadcaster)* | -| 🤖🖥️ | `lights_container` | Node for managing ROS components. This node manages: `lights_controller`, `lights_driver`. [*rclcpp_components/component_container*](https://github.com/ros2/rclcpp/tree/rolling/rclcpp_components) | -| 🤖🖥️ | `lights_controller` | This node is responsible for processing animations and publishing frames to be displayed on the Husarion Panther robot Bumper Lights. [*panther_lights/LightsControllerNode*](./panther_lights/include/panther_lights/lights_controller_node.hpp) | -| 🤖 | `lights_driver` | This node is responsible for displaying frames on the Husarion Panther robot's Bumper Lights. [*panther_lights/LightsDriverNode*](./panther_lights/include/panther_lights/lights_driver_node.hpp) | -| 🤖🖥️ | `lights_manager` | Node responsible for managing Bumper Lights animation scheduling. [panther_manager/lights_manager](./panther_manager/include/panther_manager/lights_manager_node.hpp) | -| 🤖🖥️⚙️ | `navsat_transform` | It converts raw GPS data into odometry data and publishes corrected GPS positions based on sensor data at a higher frequency. *[robot_localization/navsat_transform](https://github.com/cra-ros-pkg/robot_localization)* | -| 🖥️ | `panther_base_gz_bridge` | Convert and transmit data between ROS and Gazebo *[ros_gz_bridge/parameter_bridge](https://github.com/gazebosim/ros_gz/tree/ros2/ros_gz_bridge)* | -| 🤖🖥️ | `robot_state_publisher` | Broadcasts a robot's state to tf2 using a provided URDF model and joint states. It updates the model and broadcasts poses for fixed and movable joints to tf2 topics. *[robot_state_publisher/robot_state_publisher](https://github.com/ros/robot_state_publisher)* | -| 🤖 | `safety_manager` | Node responsible for managing safety features, and software shutdown of components. *[panther_manager/safety_manager_node](./panther_manager/include/panther_manager/safety_manager_node.hpp)* | -| 🤖 | `system_monitor` | Publishes system state of the Built-in Computer such as CPU usage, RAM memory usage, disk usage and CPU temperature. *[panther_diagnostic/system_monitor_node](./panther_diagnostics/include/panther_diagnostics/system_monitor_node.hpp)* | +| 🤖 | 🖥️ | Node name | Description | +| --- | --- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ✅ | ❌ | `battery_driver` | Publishes battery state read from ADC unit. [*panther_batter/battery_driver_node*](./husarion_ugv_battery/include/husarion_ugv_battery/battery_driver_node.hpp) | +| ✅ | ✅ | `controller_manager` | The Controller Manager performs two main functions. First, it manages controllers and their required interfaces, handling tasks like loading, activating, deactivating, and unloading. Second, it interacts with hardware components, ensuring access to their interfaces. This node manages the: `imu_broadcaster`, `joint_state_broadcaster`, `drive_controller`. *[controller_manager/controller_manager](https://github.com/ros-controls/ros2_control/blob/master/controller_manager)* | +| ✅ | ✅ | `drive_controller` | Manages mobile robots with a differential or mecanum drive depending on the configuration. It converts velocity commands for the robot body into wheel commands for the base. It also calculates odometry from hardware feedback and shares it. *[diff_drive_controller/diff_drive_controller](https://github.com/ros-controls/ros2_controllers/tree/master/diff_drive_controller) or [mecanum_drive_controller/mecanum_drive_controller](https://github.com/husarion/husarion_controllers/tree/main/mecanum_drive_controller)* | +| ✅ | ✅ | `ekf_filter` | The Extended Kalman Filter node is designed to fuse odometry data from various sources, including wheel encoders, IMU, and GPS. *[robot_localization/ekf_filter](https://github.com/cra-ros-pkg/robot_localization)* | +| ✅ | ❌ | `gps` | Node responsible for parsing NMEA strings and publishing standard ROS NavSat message types. *[nmea_navsat_driver/nmea_navsat_driver](https://github.com/ros-drivers/nmea_navsat_driver/tree/ros2/src/libnmea_navsat_driver)* | +| ❌ | ✅ | `gz_bridge` | Convert and transmit data between ROS and Gazebo *[ros_gz_bridge/parameter_bridge](https://github.com/gazebosim/ros_gz/tree/ros2/ros_gz_bridge)* | +| ❌ | ✅ | `gz_ros2_control` | Responsible for integrating the ros2_control controller architecture with the Gazebo simulator. [gz_ros2_control/gz_ros2_control](https://github.com/ros-controls/gz_ros2_control/tree/master/gz_ros2_control/src) | +| ❌ | ✅ | `gz_estop_gui` | The node is part of the Gazebo GUI plugin, enabling easy E-stop state modifications directly within the simulation. [husarion_ugv_gazebo/EStop](./husarion_ugv_gazebo/src/gui/e_stop.cpp) | +| ✅ | ❌ | `hardware_controller` | Plugin responsible for communicating with engine controllers via the CAN bus and providing E-Stop functionalities. *[husarion_ugv_hardware_interfaces/{robot_model}System](./husarion_ugv_hardware_interfaces/src/robot_system/)* | +| ✅ | ✅ | `imu_broadcaster` | Publishes readings of IMU sensors. *[imu_sensor_broadcaster/imu_sensor_broadcaster](https://github.com/ros-controls/ros2_controllers/tree/master/imu_sensor_broadcaster)* | +| ✅ | ✅ | `joint_state_broadcaster` | Reads all state interfaces and reports them on specific topics. *[joint_state_broadcaster/joint_state_broadcaster](https://github.com/ros-controls/ros2_controllers/tree/master/joint_state_broadcaster)* | +| ✅ | ✅ | `lights_container` | Node for managing ROS components. This node manages: `lights_controller`, `lights_driver`. [*rclcpp_components/component_container*](https://github.com/ros2/rclcpp/tree/rolling/rclcpp_components) | +| ✅ | ✅ | `lights_controller` | This node is responsible for processing animations and publishing frames to `light_driver` node. [*husarion_ugv_lights/LightsControllerNode*](./husarion_ugv_lights/include/husarion_ugv_lights/lights_controller_node.hpp) | +| ✅ | ❌ | `lights_driver` | This node is responsible for displaying frames on the robot's lights. [*husarion_ugv_lights/LightsDriverNode*](./husarion_ugv_lights/include/husarion_ugv_lights/lights_driver_node.hpp) | +| ✅ | ✅ | `lights_manager` | Node responsible for managing lights animation scheduling. [husarion_ugv_manager/lights_manager](./husarion_ugv_manager/include/husarion_ugv_manager/lights_manager_node.hpp) | +| ✅ | ✅ | ⚙️ `navsat_transform` ⚙️ | It converts raw GPS data into odometry data and publishes corrected GPS positions based on sensor data at a higher frequency. *[robot_localization/navsat_transform](https://github.com/cra-ros-pkg/robot_localization)* | +| ✅ | ✅ | `robot_state_publisher` | Broadcasts a robot's state to tf2 using a provided URDF model and joint states. It updates the model and broadcasts poses for fixed and movable joints to tf2 topics. *[robot_state_publisher/robot_state_publisher](https://github.com/ros/robot_state_publisher)* | +| ✅ | ❌ | `safety_manager` | Node responsible for managing safety features, and software shutdown of components. *[husarion_ugv_manager/safety_manager_node](./husarion_ugv_manager/include/husarion_ugv_manager/safety_manager_node.hpp)* | +| ✅ | ❌ | `system_monitor` | Publishes system state of the Built-in Computer such as CPU usage, RAM memory usage, disk usage and CPU temperature. *[husarion_ugv_diagnostics/system_monitor_node](./husarion_ugv_diagnostics/include/husarion_ugv_diagnostics/system_monitor_node.hpp)* | ### Topics -| | Topic | Description | -| --- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 🤖🖥️ | `battery/battery_status` | Mean values of both batteries if Panther has two batteries. Otherwise, the state of the single battery will be published. [*sensor_msgs/BatteryState*](https://docs.ros2.org/latest/api/sensor_msgs/msg/BatteryState.html) | -| 🤖 | `battery/charging_status` | Battery charging status value. [*panther_msgs/ChargingStatus*](https://github.com/husarion/panther_msgs) | -| 🤖🖥️ | `cmd_vel` | Command velocity value. [*geometry_msgs/Twist*](https://docs.ros2.org/latest/api/geometry_msgs/msg/Twist.html) | -| 🤖🖥️ | `diagnostics` | Diagnostic data. [*diagnostic_msgs/DiagnosticArray*](https://docs.ros2.org/latest/api/diagnostic_msgs/msg/DiagnosticArray.html) | -| 🤖🖥️ | `dynamic_joint_states` | Information about the state of various movable joints in a robotic system. [*control_msgs/DynamicJointState*](https://github.com/ros-controls/control_msgs/blob/master/control_msgs/msg/DynamicJointState.msg) | -| 🤖🖥️⚙️ | `gps/filtered` | Filtered GPS position after fusing odometry data. [*sensor_msgs/NavSatFix*](https://docs.ros2.org/latest/api/sensor_msgs/msg/NavSatFix.html) | -| 🤖🖥️⚙️ | `gps/fix` | Raw GPS data. [*sensor_msgs/NavSatFix*](https://docs.ros2.org/latest/api/sensor_msgs/msg/NavSatFix.html) | -| 🤖 | `gps/time_reference` | The timestamp from the GPS device. [*sensor_msgs/TimeReference*](https://docs.ros2.org/latest/api/sensor_msgs/msg/TimeReference.html) | -| 🤖 | `gps/vel` | Velocity output from the GPS device. [*geometry_msgs/TwistStamped*](https://docs.ros2.org/latest/api/geometry_msgs/msg/TwistStamped.html) | -| 🤖🖥️ | `hardware/e_stop` | Current E-stop state. [*std_msgs/Bool*](https://docs.ros2.org/latest/api/std_msgs/msg/Bool.html). | -| 🤖 | `hardware/io_state` | Current IO state. [*panther_msgs/IOState*](https://github.com/husarion/panther_msgs) | -| 🤖🖥️ | `hardware/motor_controllers_state` | Current motor controllers' state and error flags. Subscribed if using Roboteq motor controllers data. [*panther_msgs/DriverState*](https://github.com/husarion/panther_msgs) | -| 🤖🖥️ | `imu/data` | Filtered IMU data. [*sensor_msgs/Imu*](https://docs.ros2.org/latest/api/sensor_msgs/msg/Imu.html) | -| 🤖🖥️ | `joint_states` | Provides information about the state of various joints in a robotic system. [*sensor_msgs/JointState*](https://docs.ros2.org/latest/api/sensor_msgs/msg/JointState.html) | -| 🤖🖥️ | `lights/channel_1_frame` | Frame to be displayed on robot Front Bumper Lights. [*sensor_msgs/Image*](https://docs.ros2.org/latest/api/sensor_msgs/msg/Image.html) | -| 🤖🖥️ | `lights/channel_2_frame` | Frame to be displayed on robot Rear Bumper Lights. [*sensor_msgs/Image*](https://docs.ros2.org/latest/api/sensor_msgs/msg/Image.html) | -| 🤖🖥️ | `localization/set_pose` | Sets the pose of the EKF node. [*geometry_msgs/PoseWithCovarianceStamped*](https://docs.ros2.org/latest/api/geometry_msgs/msg/PoseWithCovarianceStamped.html) | -| 🤖🖥️ | `odometry/filtered` | Contains information about the filtered position and orientation. When `localization_mode` is `relative`, the position and orientation are relative to the starting point. When `localization_mode` is `enu`, the orientation is relative to the east-north-up (ENU) coordinates. [*nav_msgs/Odometry*](https://docs.ros2.org/latest/api/nav_msgs/msg/Odometry.html) | -| 🤖🖥️ | `odometry/wheels` | Robot odometry calculated from wheels. [*nav_msgs/Odometry*](https://docs.ros2.org/latest/api/nav_msgs/msg/Odometry.html) | -| 🤖🖥️ | `robot_description` | Contains information about robot description from URDF file. [*std_msgs/String*](https://docs.ros2.org/latest/api/std_msgs/msg/String.html) | -| 🤖 | `system_status` | State of the system, including Built-in Computer's CPU temperature and load. [*panther_msgs/SystemStatus*](https://github.com/husarion/panther_msgs) | -| 🤖🖥️ | `tf` | Transforms of robot system. [*tf2_msgs/TFMessage*](https://docs.ros2.org/latest/api/tf2_msgs/msg/TFMessage.html) | -| 🤖🖥️ | `tf_static` | Static transforms of robot system. [*tf2_msgs/TFMessage*](https://docs.ros2.org/latest/api/tf2_msgs/msg/TFMessage.html) | +| 🤖 | 🖥️ | Topic | Description | +| --- | --- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ✅ | ✅ | `battery/battery_status` | Mean values of both batteries will be published if the robot has two batteries. Otherwise, the state of the single battery will be published. [*sensor_msgs/BatteryState*](https://docs.ros2.org/latest/api/sensor_msgs/msg/BatteryState.html) | +| ✅ | ❌ | `battery/charging_status` | Battery charging status value. [*panther_msgs/ChargingStatus*](https://github.com/husarion/panther_msgs) | +| ✅ | ✅ | `cmd_vel` | Command velocity value. [*geometry_msgs/Twist*](https://docs.ros2.org/latest/api/geometry_msgs/msg/Twist.html) | +| ✅ | ✅ | `diagnostics` | Diagnostic data. [*diagnostic_msgs/DiagnosticArray*](https://docs.ros2.org/latest/api/diagnostic_msgs/msg/DiagnosticArray.html) | +| ✅ | ✅ | `dynamic_joint_states` | Information about the state of various movable joints in a robotic system. [*control_msgs/DynamicJointState*](https://github.com/ros-controls/control_msgs/blob/master/control_msgs/msg/DynamicJointState.msg) | +| ✅ | ✅ | ⚙️ `gps/filtered` ⚙️ | Filtered GPS position after fusing odometry data. [*sensor_msgs/NavSatFix*](https://docs.ros2.org/latest/api/sensor_msgs/msg/NavSatFix.html) | +| ✅ | ✅ | ⚙️ `gps/fix` ⚙️ | Raw GPS data. [*sensor_msgs/NavSatFix*](https://docs.ros2.org/latest/api/sensor_msgs/msg/NavSatFix.html) | +| ✅ | ❌ | `gps/time_reference` | The timestamp from the GPS device. [*sensor_msgs/TimeReference*](https://docs.ros2.org/latest/api/sensor_msgs/msg/TimeReference.html) | +| ✅ | ❌ | `gps/vel` | Velocity output from the GPS device. [*geometry_msgs/TwistStamped*](https://docs.ros2.org/latest/api/geometry_msgs/msg/TwistStamped.html) | +| ✅ | ✅ | `hardware/e_stop` | Current E-stop state. [*std_msgs/Bool*](https://docs.ros2.org/latest/api/std_msgs/msg/Bool.html). | +| ✅ | ❌ | `hardware/io_state` | Current IO state. [*panther_msgs/IOState*](https://github.com/husarion/panther_msgs) | +| ✅ | ✅ | `hardware/robot_driver_state` | Current motor controllers' state and error flags. Subscribed if using Roboteq motor controllers data. [*panther_msgs/RobotDriverState*](https://github.com/husarion/panther_msgs) | +| ✅ | ✅ | `imu/data` | Filtered IMU data. [*sensor_msgs/Imu*](https://docs.ros2.org/latest/api/sensor_msgs/msg/Imu.html) | +| ✅ | ✅ | `joint_states` | Provides information about the state of various joints in a robotic system. [*sensor_msgs/JointState*](https://docs.ros2.org/latest/api/sensor_msgs/msg/JointState.html) | +| ✅ | ✅ | `lights/channel_1_frame` | Frame to be displayed on robot Front Bumper Lights. [*sensor_msgs/Image*](https://docs.ros2.org/latest/api/sensor_msgs/msg/Image.html) | +| ✅ | ✅ | `lights/channel_2_frame` | Frame to be displayed on robot Rear Bumper Lights. [*sensor_msgs/Image*](https://docs.ros2.org/latest/api/sensor_msgs/msg/Image.html) | +| ✅ | ✅ | `localization/set_pose` | Sets the pose of the EKF node. [*geometry_msgs/PoseWithCovarianceStamped*](https://docs.ros2.org/latest/api/geometry_msgs/msg/PoseWithCovarianceStamped.html) | +| ✅ | ✅ | `odometry/filtered` | Contains information about the filtered position and orientation. When `localization_mode` is `relative`, the position and orientation are relative to the starting point. When `localization_mode` is `enu`, the orientation is relative to the east-north-up (ENU) coordinates. [*nav_msgs/Odometry*](https://docs.ros2.org/latest/api/nav_msgs/msg/Odometry.html) | +| ✅ | ✅ | `odometry/wheels` | Robot odometry calculated from wheels. [*nav_msgs/Odometry*](https://docs.ros2.org/latest/api/nav_msgs/msg/Odometry.html) | +| ✅ | ✅ | `robot_description` | Contains information about robot description from URDF file. [*std_msgs/String*](https://docs.ros2.org/latest/api/std_msgs/msg/String.html) | +| ✅ | ❌ | `system_status` | State of the system, including Built-in Computer's CPU temperature and load. [*panther_msgs/SystemStatus*](https://github.com/husarion/panther_msgs) | +| ✅ | ✅ | `tf` | Transforms of robot system. [*tf2_msgs/TFMessage*](https://docs.ros2.org/latest/api/tf2_msgs/msg/TFMessage.html) | +| ✅ | ✅ | `tf_static` | Static transforms of robot system. [*tf2_msgs/TFMessage*](https://docs.ros2.org/latest/api/tf2_msgs/msg/TFMessage.html) | #### Hidden topics -| | Topic | Description | -| --- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 🤖 | `_battery/battery_1_status_raw` | First battery raw state. [*sensor_msgs/BatteryState*](https://docs.ros2.org/latest/api/sensor_msgs/msg/BatteryState.html) | -| 🤖 | `_battery/battery_2_status_raw` | Second battery raw state. Published if second battery detected. [*sensor_msgs/BatteryState*](https://docs.ros2.org/latest/api/sensor_msgs/msg/BatteryState.html) | -| 🤖 | `_gps/heading` | Not supported for current configuration. [*geometry_msgs/QuaternionStamped*](https://docs.ros2.org/latest/api/geometry_msgs/msg/QuaternionStamped.html)| -| 🤖🖥️⚙️ | `_odometry/gps` | Transformed raw GPS data to odometry format. [*nav_msgs/Odometry*](https://docs.ros2.org/latest/api/nav_msgs/msg/Odometry.html) | +| 🤖 | 🖥️ | Topic | Description | +| --- | --- | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ✅ | ❌ | `_battery/battery_1_status_raw` | First battery raw state. [_sensor_msgs/BatteryState_](https://docs.ros2.org/latest/api/sensor_msgs/msg/BatteryState.html) | +| ✅ | ❌ | `_battery/battery_2_status_raw` | Second battery raw state. Published if second battery detected. [_sensor_msgs/BatteryState_](https://docs.ros2.org/latest/api/sensor_msgs/msg/BatteryState.html) | +| ✅ | ❌ | `_gps/heading` | Not supported for current configuration. [_geometry_msgs/QuaternionStamped_](https://docs.ros2.org/latest/api/geometry_msgs/msg/QuaternionStamped.html) | +| ✅ | ✅ | ⚙️ `_odometry/gps` ⚙️ | Transformed raw GPS data to odometry format. [_nav_msgs/Odometry_](https://docs.ros2.org/latest/api/nav_msgs/msg/Odometry.html) | ### Services -| | Service | Description | -| --- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| 🤖🖥️ | `controller_manager/configure_controller` | Manage lifecycle transition. [controller_manager_msgs/srv/ConfigureController](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | -| 🤖🖥️ | `controller_manager/list_controller_types` | Output the available controller types and their base classes. [controller_manager_msgs/srv/ListControllerTypes](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | -| 🤖🖥️ | `controller_manager/list_controllers` | Output the list of loaded controllers, their type and status. [controller_manager_msgs/srv/ListControllers](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | -| 🤖🖥️ | `controller_manager/list_hardware_components` | Output the list of available hardware components. [controller_manager_msgs/srv/ListHardwareComponents](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | -| 🤖🖥️ | `controller_manager/list_hardware_interfaces` | Output the list of available command and state interfaces. [controller_manager_msgs/srv/ListHardwareInterfaces](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | -| 🤖🖥️ | `controller_manager/load_controller` | Load a controller in a controller manager. [controller_manager_msgs/srv/LoadController](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | -| 🤖🖥️ | `controller_manager/reload_controller_libraries` | Reload controller libraries. [controller_manager_msgs/srv/ReloadControllerLibraries](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | -| 🤖🖥️ | `controller_manager/set_hardware_component_state` | Adjust the state of the hardware component. [controller_manager_msgs/srv/SetHardwareComponentState](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | -| 🤖🖥️ | `controller_manager/switch_controller` | Switch controllers in a controller manager. [controller_manager_msgs/srv/SwitchController](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | -| 🤖🖥️ | `controller_manager/unload_controller` | Unload a controller in a controller manager. [controller_manager_msgs/srv/UnloadController](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | -| 🤖 | `hardware/aux_power_enable` | Enables or disables AUX power. [std_srvs/srv/SetBool](https://docs.ros2.org/latest/api/std_srvs/srv/SetBool.html) | -| 🤖 | `hardware/charger_enable` | Enables or disables external charger. [std_srvs/srv/SetBool](https://docs.ros2.org/latest/api/std_srvs/srv/SetBool.html) | -| 🤖 | `hardware/digital_power_enable` | Enables or disables digital power. [std_srvs/srv/SetBool](https://docs.ros2.org/latest/api/std_srvs/srv/SetBool.html) | -| 🤖🖥️ | `hardware/e_stop_reset` | Resets E-stop. [std_srvs/srv/Trigger](https://docs.ros2.org/latest/api/std_srvs/srv/Trigger.html) | -| 🤖🖥️ | `hardware/e_stop_trigger` | Triggers E-stop. [std_srvs/srv/Trigger](https://docs.ros2.org/latest/api/std_srvs/srv/Trigger.html) | -| 🤖 | `hardware/fan_enable` | Enables or disables fan. [std_srvs/srv/SetBool](https://docs.ros2.org/latest/api/std_srvs/srv/SetBool.html) | -| 🤖 | `hardware/motor_power_enable` | Enables or disables motor power. [std_srvs/srv/SetBool](https://docs.ros2.org/latest/api/std_srvs/srv/SetBool.html) | -| 🤖🖥️ | `lights/set_animation` | Sets LED animation. [panther_msgs/srv/SetLEDAnimation](https://github.com/husarion/panther_msgs) | -| 🤖 | `lights/set_brightness` | Sets global LED brightness, value ranges from **0.0** to **1.0**. [panther_msgs/SetLEDBrightness](https://github.com/husarion/panther_msgs) | -| 🤖🖥️ | `localization/enable` | Enable EKF node. [std_srvs/srv/Empty](https://docs.ros2.org/latest/api/std_srvs/srv/Empty.html) | -| 🤖🖥️ | `localization/set_pose` | Set pose of EKF node. [robot_localization/srv/SetPose](https://github.com/cra-ros-pkg/robot_localization/tree/ros2) | -| 🤖🖥️ | `localization/toggle` | Toggle filter processing in the EKF node. [robot_localization/srv/ToggleFilterProcessing](https://github.com/cra-ros-pkg/robot_localization/tree/ros2) | +| 🤖 | 🖥️ | Service | Description | +| --- | --- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ✅ | ✅ | `controller_manager/configure_controller` | Manage lifecycle transition. [controller_manager_msgs/srv/ConfigureController](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | +| ✅ | ✅ | `controller_manager/list_controller_types` | Output the available controller types and their base classes. [controller_manager_msgs/srv/ListControllerTypes](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | +| ✅ | ✅ | `controller_manager/list_controllers` | Output the list of loaded controllers, their type and status. [controller_manager_msgs/srv/ListControllers](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | +| ✅ | ✅ | `controller_manager/list_hardware_components` | Output the list of available hardware components. [controller_manager_msgs/srv/ListHardwareComponents](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | +| ✅ | ✅ | `controller_manager/list_hardware_interfaces` | Output the list of available command and state interfaces. [controller_manager_msgs/srv/ListHardwareInterfaces](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | +| ✅ | ✅ | `controller_manager/load_controller` | Load a controller in a controller manager. [controller_manager_msgs/srv/LoadController](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | +| ✅ | ✅ | `controller_manager/reload_controller_libraries` | Reload controller libraries. [controller_manager_msgs/srv/ReloadControllerLibraries](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | +| ✅ | ✅ | `controller_manager/set_hardware_component_state` | Adjust the state of the hardware component. [controller_manager_msgs/srv/SetHardwareComponentState](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | +| ✅ | ✅ | `controller_manager/switch_controller` | Switch controllers in a controller manager. [controller_manager_msgs/srv/SwitchController](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | +| ✅ | ✅ | `controller_manager/unload_controller` | Unload a controller in a controller manager. [controller_manager_msgs/srv/UnloadController](https://github.com/ros-controls/ros2_control/tree/master/controller_manager_msgs) | +| ✅ | ❌ | `hardware/aux_power_enable` | Enables or disables AUX power. [std_srvs/srv/SetBool](https://docs.ros2.org/latest/api/std_srvs/srv/SetBool.html) | +| ✅ | ❌ | `hardware/charger_enable` | Enables or disables external charger. [std_srvs/srv/SetBool](https://docs.ros2.org/latest/api/std_srvs/srv/SetBool.html) | +| ✅ | ❌ | `hardware/digital_power_enable` | Enables or disables digital power. [std_srvs/srv/SetBool](https://docs.ros2.org/latest/api/std_srvs/srv/SetBool.html) | +| ✅ | ✅ | `hardware/e_stop_reset` | Resets E-stop. [std_srvs/srv/Trigger](https://docs.ros2.org/latest/api/std_srvs/srv/Trigger.html) | +| ✅ | ✅ | `hardware/e_stop_trigger` | Triggers E-stop. [std_srvs/srv/Trigger](https://docs.ros2.org/latest/api/std_srvs/srv/Trigger.html) | +| ✅ | ❌ | `hardware/fan_enable` | Enables or disables fan. [std_srvs/srv/SetBool](https://docs.ros2.org/latest/api/std_srvs/srv/SetBool.html) | +| ✅ | ❌ | `hardware/motor_power_enable` | Enables or disables motor power. [std_srvs/srv/SetBool](https://docs.ros2.org/latest/api/std_srvs/srv/SetBool.html) | +| ✅ | ✅ | `lights/set_animation` | Sets LED animation. [panther_msgs/srv/SetLEDAnimation](https://github.com/husarion/panther_msgs) | +| ✅ | ✅ | `localization/enable` | Enable EKF node. [std_srvs/srv/Empty](https://docs.ros2.org/latest/api/std_srvs/srv/Empty.html) | +| ✅ | ❌ | `lights/set_brightness` | Sets global LED brightness, value ranges from **0.0** to **1.0**. [panther_msgs/SetLEDBrightness](https://github.com/husarion/panther_msgs) | +| ✅ | ✅ | `localization/set_pose` | Set pose of EKF node. [robot_localization/srv/SetPose](https://github.com/cra-ros-pkg/robot_localization/tree/ros2) | +| ✅ | ✅ | `localization/toggle` | Toggle filter processing in the EKF node. [robot_localization/srv/ToggleFilterProcessing](https://github.com/cra-ros-pkg/robot_localization/tree/ros2) | diff --git a/panther/CHANGELOG.rst b/husarion_ugv/CHANGELOG.rst similarity index 100% rename from panther/CHANGELOG.rst rename to husarion_ugv/CHANGELOG.rst diff --git a/panther/CMakeLists.txt b/husarion_ugv/CMakeLists.txt similarity index 80% rename from panther/CMakeLists.txt rename to husarion_ugv/CMakeLists.txt index 626fc36a..2c2d0e25 100644 --- a/panther/CMakeLists.txt +++ b/husarion_ugv/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10.2) -project(panther) +project(husarion_ugv) find_package(ament_cmake REQUIRED) diff --git a/husarion_ugv/README.md b/husarion_ugv/README.md new file mode 100644 index 00000000..bc079c16 --- /dev/null +++ b/husarion_ugv/README.md @@ -0,0 +1,3 @@ +# husarion_ugv + +ROS 2 Metapackage composing basic functionalities of the Husarion UGV robot with VCS Tool yaml files directing to external robot dependencies. diff --git a/panther/panther_hardware.repos b/husarion_ugv/hardware_deps.repos similarity index 94% rename from panther/panther_hardware.repos rename to husarion_ugv/hardware_deps.repos index 27289d3b..eceb83d6 100644 --- a/panther/panther_hardware.repos +++ b/husarion_ugv/hardware_deps.repos @@ -10,7 +10,7 @@ repositories: panther_msgs: type: git url: https://github.com/husarion/panther_msgs.git - version: fcee4d9f249a62adc113eb80be4885b08024ee9c + version: ros2-devel ros_components_description: type: git url: https://github.com/husarion/ros_components_description.git diff --git a/panther/package.xml b/husarion_ugv/package.xml similarity index 71% rename from panther/package.xml rename to husarion_ugv/package.xml index 788b9385..3702562a 100644 --- a/panther/package.xml +++ b/husarion_ugv/package.xml @@ -1,9 +1,9 @@ - panther + husarion_ugv 2.1.2 - Meta package that contains all packages of Panther + Meta package that contains all packages of Husarion UGV (Unmanned Ground Vehicle) Husarion Apache License 2.0 @@ -15,8 +15,8 @@ ament_cmake - panther_bringup - panther_gazebo + husarion_ugv_bringup + husarion_ugv_gazebo ament_cmake diff --git a/panther/panther_simulation.repos b/husarion_ugv/simulation_deps.repos similarity index 95% rename from panther/panther_simulation.repos rename to husarion_ugv/simulation_deps.repos index 83df44fa..e6c81113 100644 --- a/panther/panther_simulation.repos +++ b/husarion_ugv/simulation_deps.repos @@ -10,7 +10,7 @@ repositories: panther_msgs: type: git url: https://github.com/husarion/panther_msgs.git - version: fcee4d9f249a62adc113eb80be4885b08024ee9c + version: ros2-devel ros_components_description: type: git url: https://github.com/husarion/ros_components_description.git diff --git a/panther_battery/CHANGELOG.rst b/husarion_ugv_battery/CHANGELOG.rst similarity index 100% rename from panther_battery/CHANGELOG.rst rename to husarion_ugv_battery/CHANGELOG.rst diff --git a/panther_battery/CMakeLists.txt b/husarion_ugv_battery/CMakeLists.txt similarity index 84% rename from panther_battery/CMakeLists.txt rename to husarion_ugv_battery/CMakeLists.txt index 4e12bab8..a3dc0c8d 100644 --- a/panther_battery/CMakeLists.txt +++ b/husarion_ugv_battery/CMakeLists.txt @@ -1,18 +1,24 @@ cmake_minimum_required(VERSION 3.10.2) -project(panther_battery) +project(husarion_ugv_battery) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() -set(PACKAGE_DEPENDENCIES ament_cmake diagnostic_updater panther_msgs - panther_utils rclcpp sensor_msgs) +set(PACKAGE_DEPENDENCIES + ament_cmake + diagnostic_updater + generate_parameter_library + panther_msgs + husarion_ugv_utils + rclcpp + sensor_msgs) foreach(PACKAGE IN ITEMS ${PACKAGE_DEPENDENCIES}) find_package(${PACKAGE} REQUIRED) endforeach() -include_directories(include ${panther_utils_INCLUDE_DIRS}) +include_directories(include ${husarion_ugv_utils_INCLUDE_DIRS}) add_executable( battery_driver_node @@ -25,6 +31,9 @@ add_executable( src/battery_publisher/single_battery_publisher.cpp) ament_target_dependencies(battery_driver_node ${PACKAGE_DEPENDENCIES}) +generate_parameter_library(battery_parameters config/battery_parameters.yaml) +target_link_libraries(battery_driver_node battery_parameters) + install(TARGETS battery_driver_node DESTINATION lib/${PROJECT_NAME}) install(DIRECTORY launch DESTINATION share/${PROJECT_NAME}) @@ -76,6 +85,8 @@ if(BUILD_TESTING) $) ament_target_dependencies(${PROJECT_NAME}_test_battery_publisher ${PACKAGE_DEPENDENCIES}) + target_link_libraries(${PROJECT_NAME}_test_battery_publisher + battery_parameters) ament_add_gtest( ${PROJECT_NAME}_test_single_battery_publisher @@ -89,6 +100,8 @@ if(BUILD_TESTING) $) ament_target_dependencies(${PROJECT_NAME}_test_single_battery_publisher ${PACKAGE_DEPENDENCIES}) + target_link_libraries(${PROJECT_NAME}_test_single_battery_publisher + battery_parameters) ament_add_gtest( ${PROJECT_NAME}_test_dual_battery_publisher @@ -102,6 +115,8 @@ if(BUILD_TESTING) $) ament_target_dependencies(${PROJECT_NAME}_test_dual_battery_publisher ${PACKAGE_DEPENDENCIES}) + target_link_libraries(${PROJECT_NAME}_test_dual_battery_publisher + battery_parameters) ament_add_gtest( ${PROJECT_NAME}_test_battery_driver_node_adc_dual @@ -118,6 +133,8 @@ if(BUILD_TESTING) $) ament_target_dependencies(${PROJECT_NAME}_test_battery_driver_node_adc_dual ${PACKAGE_DEPENDENCIES}) + target_link_libraries(${PROJECT_NAME}_test_battery_driver_node_adc_dual + battery_parameters) ament_add_gtest( ${PROJECT_NAME}_test_battery_driver_node_adc_single @@ -134,6 +151,8 @@ if(BUILD_TESTING) $) ament_target_dependencies(${PROJECT_NAME}_test_battery_driver_node_adc_single ${PACKAGE_DEPENDENCIES}) + target_link_libraries(${PROJECT_NAME}_test_battery_driver_node_adc_single + battery_parameters) ament_add_gtest( ${PROJECT_NAME}_test_battery_driver_node_roboteq @@ -150,6 +169,8 @@ if(BUILD_TESTING) $) ament_target_dependencies(${PROJECT_NAME}_test_battery_driver_node_roboteq ${PACKAGE_DEPENDENCIES}) + target_link_libraries(${PROJECT_NAME}_test_battery_driver_node_roboteq + battery_parameters) endif() diff --git a/panther_battery/README.md b/husarion_ugv_battery/README.md similarity index 55% rename from panther_battery/README.md rename to husarion_ugv_battery/README.md index dc151104..263ea252 100644 --- a/panther_battery/README.md +++ b/husarion_ugv_battery/README.md @@ -1,6 +1,6 @@ -# panther_battery +# husarion_ugv_battery -The package containing nodes monitoring and publishing the internal battery state of the Husarion Panther robot. +The package containing nodes monitoring and publishing the internal battery state of the Husarion UGV. ## Launch Files @@ -8,32 +8,36 @@ This package contains: - `battery.launch.py`: Responsible for activating battery node, which dealing with reading and publishing battery data. +## Configuration Files + +- [`battery_parameters.yaml`](./config/battery_parameters.yaml): Defines parameters for `battery_driver_node`. + ## ROS Nodes ### battery_driver_node -Publishes battery state read from ADC unit for Panther version 1.2 and above, or based on Roboteq motor controllers' data for earlier.versions of the robot. +Publishes battery state read from ADC unit. #### Publishes - `_battery/battery_1_status_raw` [*sensor_msgs/BatteryState*]: First battery raw state. - `_battery/battery_2_status_raw` [*sensor_msgs/BatteryState*]: Second battery raw state. Published if second battery detected. -- `battery/battery_status` [*sensor_msgs/BatteryState*]: Mean values of both batteries if Panther has two batteries. Otherwise, the state of the single battery will be published. +- `battery/battery_status` [*sensor_msgs/BatteryState*]: Mean values of both batteries if robot has two batteries. Otherwise, the state of the single battery will be published. - `battery/charging_status` [*panther_msgs/ChargingStatus*]: Battery charging status. - `diagnostics` [*diagnostic_msgs/DiagnosticArray*]: Battery diagnostic messages. #### Subscribers - `hardware/io_state` [*panther_msgs/IOState*]: Current state of IO. -- `hardware/motor_controllers_state` [*panther_msgs/DriverState*]: Current motor controllers' state and error flags. Subscribed if using Roboteq motor controllers data. +- `hardware/robot_driver_state` [*panther_msgs/RobotDriverState*]: Current motor controllers' state and error flags. Subscribed if using Roboteq motor controllers data. #### Parameters -- `~/adc/device0` [*string*, default: **/sys/bus/iio/devices/iio:device0**]: ADC nr 0 IIO device. Used with Panther version 1.2 and above. -- `~/adc/device1` [*string*, default: **/sys/bus/iio/devices/iio:device1**]: ADC nr 1 IIO device. Used with Panther version 1.2 and above. -- `~/adc/ma_window_len/charge` [*int*, default: **10**]: Window length of a moving average, used to smooth out battery charge readings. Used with Panther version 1.2 and above. -- `~/adc/ma_window_len/temp` [*int*, default: **10**]: Window length of a moving average, used to smooth out battery temperature readings. Used with Panther version 1.2 and above. +- `~/adc.device0` [*string*, default: **/sys/bus/iio/devices/iio:device0**]: ADC number 0 IIO device. +- `~/adc.device1` [*string*, default: **/sys/bus/iio/devices/iio:device1**]: ADC number 1 IIO device. +- `~/adc.ma_window_len.charge` [*int*, default: **10**]: Window length of a moving average, used to smooth out battery charge readings. +- `~/adc.ma_window_len.temp` [*int*, default: **10**]: Window length of a moving average, used to smooth out battery temperature readings. - `~/battery_timeout` [*float*, default: **1.0**]: Specifies the timeout in seconds. If the node fails to read battery data exceeding this duration, the node will publish an unknown battery state. -- `~/ma_window_len/voltage` [*int*, default: **10**]: Window length of a moving average, used to smooth out battery voltage readings. -- `~/ma_window_len/current` [*int*, default: **10**]: Window length of a moving average, used to smooth out battery current readings. -- `~/roboteq/driver_state_timeout` [*float*, default: **0.2**]: Specifies timeout in seconds after which driver state messages will be considered old. Used with Panther version 1.06 and earlier. +- `~/ma_window_len.voltage` [*int*, default: **10**]: Window length of a moving average, used to smooth out battery voltage readings. +- `~/ma_window_len.current` [*int*, default: **10**]: Window length of a moving average, used to smooth out battery current readings. +- `~/roboteq.driver_state_timeout` [*float*, default: **0.2**]: Specifies timeout in seconds after which driver state messages will be considered old (deprecated). diff --git a/husarion_ugv_battery/config/battery_parameters.yaml b/husarion_ugv_battery/config/battery_parameters.yaml new file mode 100644 index 00000000..ab09541c --- /dev/null +++ b/husarion_ugv_battery/config/battery_parameters.yaml @@ -0,0 +1,52 @@ +battery: + adc: + device0: + type: string + default_value: "/sys/bus/iio/devices/iio:device0" + description: "Internal ADC0 IIO device." + validation: { not_empty<> } + + device1: + type: string + default_value: "/sys/bus/iio/devices/iio:device1" + description: "Internal ADC1 IIO device." + validation: { not_empty<> } + + ma_window_len: + charge: + type: int + default_value: 10 + description: "Window length of a moving average, used to smooth out battery charge readings." + validation: { gt<>: 0 } + + temp: + type: int + default_value: 10 + description: "Window length of a moving average, used to smooth out battery temperature readings." + validation: { gt<>: 0 } + + ma_window_len: + voltage: + type: int + default_value: 10 + description: "Window length of a moving average, used to smooth out battery voltage readings." + validation: { gt<>: 0 } + + current: + type: int + default_value: 10 + description: "Window length of a moving average, used to smooth out battery current readings." + validation: { gt<>: 0 } + + roboteq: + driver_state_timeout: + type: double + default_value: 0.2 + description: "Timeout in seconds after which driver state messages will be considered old. Used as a fallback when ADC data is not available." + validation: { gt<>: 0.0 } + + battery_timeout: + type: double + default_value: 1.0 + description: "Timeout in seconds. If the node fails to read battery data exceeding this duration, the node will publish an unknown battery state." + validation: { gt<>: 0.0 } diff --git a/panther_battery/include/panther_battery/adc_data_reader.hpp b/husarion_ugv_battery/include/husarion_ugv_battery/adc_data_reader.hpp similarity index 90% rename from panther_battery/include/panther_battery/adc_data_reader.hpp rename to husarion_ugv_battery/include/husarion_ugv_battery/adc_data_reader.hpp index 08dca0d0..59e1fb57 100644 --- a/panther_battery/include/panther_battery/adc_data_reader.hpp +++ b/husarion_ugv_battery/include/husarion_ugv_battery/adc_data_reader.hpp @@ -12,15 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_BATTERY_ADC_DATA_READER_HPP_ -#define PANTHER_BATTERY_ADC_DATA_READER_HPP_ +#ifndef HUSARION_UGV_BATTERY_ADC_DATA_READER_HPP_ +#define HUSARION_UGV_BATTERY_ADC_DATA_READER_HPP_ #include #include #include #include -namespace panther_battery +namespace husarion_ugv_battery { class ADCDataReader @@ -75,6 +75,6 @@ class ADCDataReader const std::filesystem::path device_path_; }; -} // namespace panther_battery +} // namespace husarion_ugv_battery -#endif // PANTHER_BATTERY_ADC_DATA_READER_HPP_ +#endif // HUSARION_UGV_BATTERY_ADC_DATA_READER_HPP_ diff --git a/panther_battery/include/panther_battery/battery/adc_battery.hpp b/husarion_ugv_battery/include/husarion_ugv_battery/battery/adc_battery.hpp similarity index 76% rename from panther_battery/include/panther_battery/battery/adc_battery.hpp rename to husarion_ugv_battery/include/husarion_ugv_battery/battery/adc_battery.hpp index 6aebfa09..20b39591 100644 --- a/panther_battery/include/panther_battery/battery/adc_battery.hpp +++ b/husarion_ugv_battery/include/husarion_ugv_battery/battery/adc_battery.hpp @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_BATTERY_BATTERY_ADC_BATTERY_HPP_ -#define PANTHER_BATTERY_BATTERY_ADC_BATTERY_HPP_ +#ifndef HUSARION_UGV_BATTERY_BATTERY_ADC_BATTERY_HPP_ +#define HUSARION_UGV_BATTERY_BATTERY_ADC_BATTERY_HPP_ #include #include @@ -21,10 +21,10 @@ #include "rclcpp/rclcpp.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_utils/moving_average.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_utils/moving_average.hpp" -namespace panther_battery +namespace husarion_ugv_battery { using BatteryStateMsg = sensor_msgs::msg::BatteryState; @@ -77,7 +77,12 @@ class ADCBattery : public Battery static constexpr float kR1 = 10000.0; static constexpr float kR0 = 10000.0; static constexpr float kUSupply = 3.28; - static constexpr float kKelvinToCelciusOffset = 273.15; + static constexpr float kKelvinToCelsiusOffset = 273.15; + + // Threshold used for diagnostics. At this voltage level, and below, the battery shall draw a + // significant current from the charger if the charger is connected. If not, the charging circuit + // may be broken. + static constexpr float kBatteryCCCheckTresh = 41.2; float voltage_raw_; float current_raw_; @@ -89,12 +94,12 @@ class ADCBattery : public Battery const std::function ReadTemp; const std::function ReadCharge; - std::unique_ptr> voltage_ma_; - std::unique_ptr> current_ma_; - std::unique_ptr> temp_ma_; - std::unique_ptr> charge_ma_; + std::unique_ptr> voltage_ma_; + std::unique_ptr> current_ma_; + std::unique_ptr> temp_ma_; + std::unique_ptr> charge_ma_; }; -} // namespace panther_battery +} // namespace husarion_ugv_battery -#endif // PANTHER_BATTERY_BATTERY_ADC_BATTERY_HPP_ +#endif // HUSARION_UGV_BATTERY_BATTERY_ADC_BATTERY_HPP_ diff --git a/panther_battery/include/panther_battery/battery/battery.hpp b/husarion_ugv_battery/include/husarion_ugv_battery/battery/battery.hpp similarity index 86% rename from panther_battery/include/panther_battery/battery/battery.hpp rename to husarion_ugv_battery/include/husarion_ugv_battery/battery/battery.hpp index eb067aa6..94392164 100644 --- a/panther_battery/include/panther_battery/battery/battery.hpp +++ b/husarion_ugv_battery/include/husarion_ugv_battery/battery/battery.hpp @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_BATTERY_BATTERY_BATTERY_HPP_ -#define PANTHER_BATTERY_BATTERY_BATTERY_HPP_ +#ifndef HUSARION_UGV_BATTERY_BATTERY_BATTERY_HPP_ +#define HUSARION_UGV_BATTERY_BATTERY_BATTERY_HPP_ #include #include @@ -27,7 +27,7 @@ #include "panther_msgs/msg/charging_status.hpp" -namespace panther_battery +namespace husarion_ugv_battery { using BatteryStateMsg = sensor_msgs::msg::BatteryState; @@ -57,14 +57,14 @@ class Battery float GetBatteryPercent(const float voltage) const { - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 5; i++) { if (voltage > battery_approx_ranges[i]) { return std::clamp( (battery_approx_a_values[i] * voltage + battery_approx_b_values[i]) / 100, 0.0f, 1.0f); } } return std::clamp( - (battery_approx_a_values[4] * voltage + battery_approx_b_values[4]) / 100, 0.0f, 1.0f); + (battery_approx_a_values[5] * voltage + battery_approx_b_values[5]) / 100, 0.0f, 1.0f); } void ResetBatteryMsgs(const rclcpp::Time & header_stamp) @@ -117,9 +117,10 @@ class Battery static constexpr float kDesignedCapacity = 20.0; static constexpr std::string_view kLocation = "user_compartment"; - static constexpr float battery_approx_ranges[4] = {41.25, 37, 35, 33.7}; - static constexpr float battery_approx_a_values[5] = {1.733, 9.153, 19.8, 10.538, 0.989}; - static constexpr float battery_approx_b_values[5] = {27.214, -278.861, -672.6, -351.47, -29.67}; + static constexpr float battery_approx_ranges[5] = {41.25, 37.0, 36.0, 35.0, 33.7}; + static constexpr float battery_approx_a_values[6] = {8.665, 9.153, 19.8, 22.84, 10.538, 0.989}; + static constexpr float battery_approx_b_values[6] = {-258.73, -278.861, -672.6, + -782.04, -351.47, -29.669}; std::string error_msg_; BatteryStateMsg battery_state_; @@ -127,6 +128,6 @@ class Battery ChargingStatusMsg charging_status_; }; -} // namespace panther_battery +} // namespace husarion_ugv_battery -#endif // PANTHER_BATTERY_BATTERY_BATTERY_HPP_ +#endif // HUSARION_UGV_BATTERY_BATTERY_BATTERY_HPP_ diff --git a/panther_battery/include/panther_battery/battery/roboteq_battery.hpp b/husarion_ugv_battery/include/husarion_ugv_battery/battery/roboteq_battery.hpp similarity index 61% rename from panther_battery/include/panther_battery/battery/roboteq_battery.hpp rename to husarion_ugv_battery/include/husarion_ugv_battery/battery/roboteq_battery.hpp index a0019fc5..0b785f79 100644 --- a/panther_battery/include/panther_battery/battery/roboteq_battery.hpp +++ b/husarion_ugv_battery/include/husarion_ugv_battery/battery/roboteq_battery.hpp @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_BATTERY_BATTERY_ROBOTEQ_BATTERY_HPP_ -#define PANTHER_BATTERY_BATTERY_ROBOTEQ_BATTERY_HPP_ +#ifndef HUSARION_UGV_BATTERY_BATTERY_ROBOTEQ_BATTERY_HPP_ +#define HUSARION_UGV_BATTERY_BATTERY_ROBOTEQ_BATTERY_HPP_ #include #include @@ -21,15 +21,17 @@ #include "rclcpp/rclcpp.hpp" -#include "panther_msgs/msg/driver_state.hpp" +#include "panther_msgs/msg/driver_state_named.hpp" +#include "panther_msgs/msg/robot_driver_state.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_utils/moving_average.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_utils/moving_average.hpp" -namespace panther_battery +namespace husarion_ugv_battery { -using DriverStateMsg = panther_msgs::msg::DriverState; +using RobotDriverStateMsg = panther_msgs::msg::RobotDriverState; +using DriverStateNamedMsg = panther_msgs::msg::DriverStateNamed; struct RoboteqBatteryParams { @@ -42,7 +44,7 @@ class RoboteqBattery : public Battery { public: RoboteqBattery( - const std::function & get_driver_state, + const std::function & get_driver_state, const RoboteqBatteryParams & params); ~RoboteqBattery() {} @@ -54,7 +56,7 @@ class RoboteqBattery : public Battery float GetLoadCurrent() override { return std::numeric_limits::quiet_NaN(); } protected: - void ValidateDriverStateMsg(const rclcpp::Time & header_stamp); + void ValidateRobotDriverStateMsg(const rclcpp::Time & header_stamp); private: void UpdateBatteryMsgs(const rclcpp::Time & header_stamp); @@ -62,18 +64,19 @@ class RoboteqBattery : public Battery void UpdateBatteryStateRaw(); void UpdateChargingStatus(const rclcpp::Time & header_stamp); std::uint8_t GetBatteryHealth(const float voltage); + bool DriverStateHeartbeatTimeout(); - std::function GetDriverState; + std::function GetRobotDriverState; const float driver_state_timeout_; float voltage_raw_; float current_raw_; - DriverStateMsg::SharedPtr driver_state_; + RobotDriverStateMsg::SharedPtr driver_state_; - std::unique_ptr> voltage_ma_; - std::unique_ptr> current_ma_; + std::unique_ptr> voltage_ma_; + std::unique_ptr> current_ma_; }; -} // namespace panther_battery +} // namespace husarion_ugv_battery -#endif // PANTHER_BATTERY_BATTERY_ROBOTEQ_BATTERY_HPP_ +#endif // HUSARION_UGV_BATTERY_BATTERY_ROBOTEQ_BATTERY_HPP_ diff --git a/panther_battery/include/panther_battery/battery_driver_node.hpp b/husarion_ugv_battery/include/husarion_ugv_battery/battery_driver_node.hpp similarity index 65% rename from panther_battery/include/panther_battery/battery_driver_node.hpp rename to husarion_ugv_battery/include/husarion_ugv_battery/battery_driver_node.hpp index c13371c9..ca113540 100644 --- a/panther_battery/include/panther_battery/battery_driver_node.hpp +++ b/husarion_ugv_battery/include/husarion_ugv_battery/battery_driver_node.hpp @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_BATTERY_BATTERY_DRIVER_NODE_HPP_ -#define PANTHER_BATTERY_BATTERY_DRIVER_NODE_HPP_ +#ifndef HUSARION_UGV_BATTERY_BATTERY_DRIVER_NODE_HPP_ +#define HUSARION_UGV_BATTERY_BATTERY_DRIVER_NODE_HPP_ #include #include @@ -21,16 +21,18 @@ #include "diagnostic_updater/diagnostic_updater.hpp" #include "rclcpp/rclcpp.hpp" -#include "panther_msgs/msg/driver_state.hpp" +#include "panther_msgs/msg/robot_driver_state.hpp" -#include "panther_battery/adc_data_reader.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_battery/battery_publisher/battery_publisher.hpp" +#include "battery_parameters.hpp" -namespace panther_battery +#include "husarion_ugv_battery/adc_data_reader.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_battery/battery_publisher/battery_publisher.hpp" + +namespace husarion_ugv_battery { -using DriverStateMsg = panther_msgs::msg::DriverState; +using RobotDriverStateMsg = panther_msgs::msg::RobotDriverState; class BatteryDriverNode : public rclcpp::Node { @@ -46,7 +48,7 @@ class BatteryDriverNode : public rclcpp::Node static constexpr int kADCCurrentOffset = 625; - DriverStateMsg::SharedPtr driver_state_; + RobotDriverStateMsg::SharedPtr driver_state_; std::shared_ptr adc0_reader_; std::shared_ptr adc1_reader_; @@ -54,12 +56,15 @@ class BatteryDriverNode : public rclcpp::Node std::shared_ptr battery_2_; std::shared_ptr battery_publisher_; - rclcpp::Subscription::SharedPtr driver_state_sub_; + std::shared_ptr param_listener_; + battery::Params params_; + + rclcpp::Subscription::SharedPtr driver_state_sub_; rclcpp::TimerBase::SharedPtr battery_pub_timer_; std::shared_ptr diagnostic_updater_; }; -} // namespace panther_battery +} // namespace husarion_ugv_battery -#endif // PANTHER_BATTERY_BATTERY_DRIVER_NODE_HPP_ +#endif // HUSARION_UGV_BATTERY_BATTERY_DRIVER_NODE_HPP_ diff --git a/panther_battery/include/panther_battery/battery_publisher/battery_publisher.hpp b/husarion_ugv_battery/include/husarion_ugv_battery/battery_publisher/battery_publisher.hpp similarity index 86% rename from panther_battery/include/panther_battery/battery_publisher/battery_publisher.hpp rename to husarion_ugv_battery/include/husarion_ugv_battery/battery_publisher/battery_publisher.hpp index 688f1899..29e52609 100644 --- a/panther_battery/include/panther_battery/battery_publisher/battery_publisher.hpp +++ b/husarion_ugv_battery/include/husarion_ugv_battery/battery_publisher/battery_publisher.hpp @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_BATTERY_BATTERY_PUBLISHER_BATTERY_PUBLISHER_HPP_ -#define PANTHER_BATTERY_BATTERY_PUBLISHER_BATTERY_PUBLISHER_HPP_ +#ifndef HUSARION_UGV_BATTERY_BATTERY_PUBLISHER_BATTERY_PUBLISHER_HPP_ +#define HUSARION_UGV_BATTERY_BATTERY_PUBLISHER_BATTERY_PUBLISHER_HPP_ #include @@ -25,7 +25,7 @@ #include "panther_msgs/msg/charging_status.hpp" #include "panther_msgs/msg/io_state.hpp" -namespace panther_battery +namespace husarion_ugv_battery { using BatteryStateMsg = sensor_msgs::msg::BatteryState; @@ -37,7 +37,8 @@ class BatteryPublisher public: BatteryPublisher( const rclcpp::Node::SharedPtr & node, - const std::shared_ptr & diagnostic_updater); + const std::shared_ptr & diagnostic_updater, + const double battery_timeout); ~BatteryPublisher() {} @@ -71,6 +72,6 @@ class BatteryPublisher rclcpp::Subscription::SharedPtr io_state_sub_; }; -} // namespace panther_battery +} // namespace husarion_ugv_battery -#endif // PANTHER_BATTERY_BATTERY_PUBLISHER_BATTERY_PUBLISHER_HPP_ +#endif // HUSARION_UGV_BATTERY_BATTERY_PUBLISHER_BATTERY_PUBLISHER_HPP_ diff --git a/panther_battery/include/panther_battery/battery_publisher/dual_battery_publisher.hpp b/husarion_ugv_battery/include/husarion_ugv_battery/battery_publisher/dual_battery_publisher.hpp similarity index 79% rename from panther_battery/include/panther_battery/battery_publisher/dual_battery_publisher.hpp rename to husarion_ugv_battery/include/husarion_ugv_battery/battery_publisher/dual_battery_publisher.hpp index 9890465f..4200c621 100644 --- a/panther_battery/include/panther_battery/battery_publisher/dual_battery_publisher.hpp +++ b/husarion_ugv_battery/include/husarion_ugv_battery/battery_publisher/dual_battery_publisher.hpp @@ -12,18 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_BATTERY_BATTERY_PUBLISHER_DUAL_BATTERY_PUBLISHER_HPP_ -#define PANTHER_BATTERY_BATTERY_PUBLISHER_DUAL_BATTERY_PUBLISHER_HPP_ +#ifndef HUSARION_UGV_BATTERY_BATTERY_PUBLISHER_DUAL_BATTERY_PUBLISHER_HPP_ +#define HUSARION_UGV_BATTERY_BATTERY_PUBLISHER_DUAL_BATTERY_PUBLISHER_HPP_ #include #include #include "rclcpp/rclcpp.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_battery/battery_publisher/battery_publisher.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_battery/battery_publisher/battery_publisher.hpp" -namespace panther_battery +namespace husarion_ugv_battery { class DualBatteryPublisher : public BatteryPublisher @@ -32,7 +32,8 @@ class DualBatteryPublisher : public BatteryPublisher DualBatteryPublisher( const rclcpp::Node::SharedPtr & node, const std::shared_ptr & diagnostic_updater, - const std::shared_ptr & battery_1, const std::shared_ptr & battery_2); + const double battery_timeout, const std::shared_ptr & battery_1, + const std::shared_ptr & battery_2); ~DualBatteryPublisher() {} @@ -66,6 +67,6 @@ class DualBatteryPublisher : public BatteryPublisher rclcpp::Publisher::SharedPtr charging_status_pub_; }; -} // namespace panther_battery +} // namespace husarion_ugv_battery -#endif // PANTHER_BATTERY_BATTERY_PUBLISHER_DUAL_BATTERY_PUBLISHER_HPP_ +#endif // HUSARION_UGV_BATTERY_BATTERY_PUBLISHER_DUAL_BATTERY_PUBLISHER_HPP_ diff --git a/panther_battery/include/panther_battery/battery_publisher/single_battery_publisher.hpp b/husarion_ugv_battery/include/husarion_ugv_battery/battery_publisher/single_battery_publisher.hpp similarity index 74% rename from panther_battery/include/panther_battery/battery_publisher/single_battery_publisher.hpp rename to husarion_ugv_battery/include/husarion_ugv_battery/battery_publisher/single_battery_publisher.hpp index 29be9bc5..1b68e2e9 100644 --- a/panther_battery/include/panther_battery/battery_publisher/single_battery_publisher.hpp +++ b/husarion_ugv_battery/include/husarion_ugv_battery/battery_publisher/single_battery_publisher.hpp @@ -12,17 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_BATTERY_BATTERY_PUBLISHER_SINGLE_BATTERY_PUBLISHER_HPP_ -#define PANTHER_BATTERY_BATTERY_PUBLISHER_SINGLE_BATTERY_PUBLISHER_HPP_ +#ifndef HUSARION_UGV_BATTERY_BATTERY_PUBLISHER_SINGLE_BATTERY_PUBLISHER_HPP_ +#define HUSARION_UGV_BATTERY_BATTERY_PUBLISHER_SINGLE_BATTERY_PUBLISHER_HPP_ #include #include "rclcpp/rclcpp.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_battery/battery_publisher/battery_publisher.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_battery/battery_publisher/battery_publisher.hpp" -namespace panther_battery +namespace husarion_ugv_battery { class SingleBatteryPublisher : public BatteryPublisher @@ -31,7 +31,7 @@ class SingleBatteryPublisher : public BatteryPublisher SingleBatteryPublisher( const rclcpp::Node::SharedPtr & node, const std::shared_ptr & diagnostic_updater, - const std::shared_ptr & battery); + const double battery_timeout, const std::shared_ptr & battery); ~SingleBatteryPublisher() {} @@ -51,6 +51,6 @@ class SingleBatteryPublisher : public BatteryPublisher rclcpp::Publisher::SharedPtr charging_status_pub_; }; -} // namespace panther_battery +} // namespace husarion_ugv_battery -#endif // PANTHER_BATTERY_BATTERY_PUBLISHER_SINGLE_BATTERY_PUBLISHER_HPP_ +#endif // HUSARION_UGV_BATTERY_BATTERY_PUBLISHER_SINGLE_BATTERY_PUBLISHER_HPP_ diff --git a/panther_battery/launch/battery.launch.py b/husarion_ugv_battery/launch/battery.launch.py similarity index 88% rename from panther_battery/launch/battery.launch.py rename to husarion_ugv_battery/launch/battery.launch.py index 3719d587..d8327e33 100644 --- a/panther_battery/launch/battery.launch.py +++ b/husarion_ugv_battery/launch/battery.launch.py @@ -28,13 +28,10 @@ def generate_launch_description(): description="Add namespace to all launched nodes.", ) - panther_version = EnvironmentVariable(name="PANTHER_ROBOT_VERSION", default_value="1.0") - battery_driver_node = Node( - package="panther_battery", + package="husarion_ugv_battery", executable="battery_driver_node", name="battery_driver", - parameters=[{"panther_version": panther_version}], namespace=namespace, remappings=[("/diagnostics", "diagnostics")], emulate_tty=True, diff --git a/panther_battery/package.xml b/husarion_ugv_battery/package.xml similarity index 89% rename from panther_battery/package.xml rename to husarion_ugv_battery/package.xml index 53e7fab8..2f77ad8f 100644 --- a/panther_battery/package.xml +++ b/husarion_ugv_battery/package.xml @@ -1,7 +1,7 @@ - panther_battery + husarion_ugv_battery 2.1.2 Nodes monitoring the battery state of Husarion Panhter robot Husarion @@ -17,8 +17,9 @@ ament_cmake diagnostic_updater + generate_parameter_library + husarion_ugv_utils panther_msgs - panther_utils rclcpp sensor_msgs diff --git a/panther_battery/src/battery/adc_battery.cpp b/husarion_ugv_battery/src/battery/adc_battery.cpp similarity index 91% rename from panther_battery/src/battery/adc_battery.cpp rename to husarion_ugv_battery/src/battery/adc_battery.cpp index 968f4823..68db4d73 100644 --- a/panther_battery/src/battery/adc_battery.cpp +++ b/husarion_ugv_battery/src/battery/adc_battery.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "panther_battery/battery/adc_battery.hpp" +#include "husarion_ugv_battery/battery/adc_battery.hpp" #include #include @@ -24,9 +24,9 @@ #include "rclcpp/rclcpp.hpp" -#include "panther_utils/moving_average.hpp" +#include "husarion_ugv_utils/moving_average.hpp" -namespace panther_battery +namespace husarion_ugv_battery { ADCBattery::ADCBattery( @@ -35,13 +35,13 @@ ADCBattery::ADCBattery( const ADCBatteryParams & params) : ReadVoltage(read_voltage), ReadCurrent(read_current), ReadTemp(read_temp), ReadCharge(read_charge) { - voltage_ma_ = std::make_unique>( + voltage_ma_ = std::make_unique>( params.voltage_window_len, std::numeric_limits::quiet_NaN()); - current_ma_ = std::make_unique>( + current_ma_ = std::make_unique>( params.current_window_len, std::numeric_limits::quiet_NaN()); - temp_ma_ = std::make_unique>( + temp_ma_ = std::make_unique>( params.temp_window_len, std::numeric_limits::quiet_NaN()); - charge_ma_ = std::make_unique>( + charge_ma_ = std::make_unique>( params.charge_window_len, std::numeric_limits::quiet_NaN()); } @@ -107,7 +107,7 @@ float ADCBattery::ADCToBatteryTemp(const float adc_data) const const float R_therm = (adc_data * kR1) / (kUSupply - adc_data); return (kTempCoeffA * kTempCoeffB / (kTempCoeffA * logf(R_therm / kR0) + kTempCoeffB)) - - kKelvinToCelciusOffset; + kKelvinToCelsiusOffset; } void ADCBattery::UpdateBatteryMsgs(const rclcpp::Time & header_stamp, const bool charger_connected) @@ -167,7 +167,7 @@ std::uint8_t ADCBattery::GetBatteryStatus(const float charge, const bool charger if (charger_connected) { if (fabs(battery_state_.percentage - 1.0f) < std::numeric_limits::epsilon()) { return BatteryStateMsg::POWER_SUPPLY_STATUS_FULL; - } else if (charge > kChargingCurrentTresh) { + } else if (charge > kChargingCurrentTresh || battery_state_.voltage > kBatteryCCCheckTresh) { return BatteryStateMsg::POWER_SUPPLY_STATUS_CHARGING; } else { return BatteryStateMsg::POWER_SUPPLY_STATUS_NOT_CHARGING; @@ -197,4 +197,4 @@ std::uint8_t ADCBattery::GetBatteryHealth(const float voltage, const float temp) } } -} // namespace panther_battery +} // namespace husarion_ugv_battery diff --git a/panther_battery/src/battery/roboteq_battery.cpp b/husarion_ugv_battery/src/battery/roboteq_battery.cpp similarity index 76% rename from panther_battery/src/battery/roboteq_battery.cpp rename to husarion_ugv_battery/src/battery/roboteq_battery.cpp index 6653208e..7d2d870d 100644 --- a/panther_battery/src/battery/roboteq_battery.cpp +++ b/husarion_ugv_battery/src/battery/roboteq_battery.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "panther_battery/battery/roboteq_battery.hpp" +#include "husarion_ugv_battery/battery/roboteq_battery.hpp" #include #include @@ -23,19 +23,19 @@ #include "rclcpp/rclcpp.hpp" -#include "panther_utils/moving_average.hpp" +#include "husarion_ugv_utils/moving_average.hpp" -namespace panther_battery +namespace husarion_ugv_battery { RoboteqBattery::RoboteqBattery( - const std::function & get_driver_state, + const std::function & get_driver_state, const RoboteqBatteryParams & params) -: GetDriverState(get_driver_state), driver_state_timeout_(params.driver_state_timeout) +: GetRobotDriverState(get_driver_state), driver_state_timeout_(params.driver_state_timeout) { - voltage_ma_ = std::make_unique>( + voltage_ma_ = std::make_unique>( params.voltage_window_len, std::numeric_limits::quiet_NaN()); - current_ma_ = std::make_unique>( + current_ma_ = std::make_unique>( params.current_window_len, std::numeric_limits::quiet_NaN()); } @@ -43,11 +43,20 @@ bool RoboteqBattery::Present() { return true; } void RoboteqBattery::Update(const rclcpp::Time & header_stamp, const bool /* charger_connected */) { - driver_state_ = GetDriverState(); - ValidateDriverStateMsg(header_stamp); - - voltage_raw_ = (driver_state_->front.voltage + driver_state_->rear.voltage) / 2.0f; - current_raw_ = driver_state_->front.current + driver_state_->rear.current; + driver_state_ = GetRobotDriverState(); + ValidateRobotDriverStateMsg(header_stamp); + + float voltage = 0.0f; + float current = 0.0f; + std::for_each( + driver_state_->driver_states.begin(), driver_state_->driver_states.end(), + [&voltage, ¤t](const DriverStateNamedMsg & driver) { + voltage += driver.state.voltage; + current += driver.state.current; + }); + + voltage_raw_ = voltage / driver_state_->driver_states.size(); + current_raw_ = current; voltage_ma_->Roll(voltage_raw_); current_ma_->Roll(current_raw_); @@ -63,7 +72,7 @@ void RoboteqBattery::Reset(const rclcpp::Time & header_stamp) SetErrorMsg(""); } -void RoboteqBattery::ValidateDriverStateMsg(const rclcpp::Time & header_stamp) +void RoboteqBattery::ValidateRobotDriverStateMsg(const rclcpp::Time & header_stamp) { if (!driver_state_) { throw std::runtime_error("Waiting for driver state message to arrive."); @@ -74,7 +83,7 @@ void RoboteqBattery::ValidateDriverStateMsg(const rclcpp::Time & header_stamp) throw std::runtime_error("Driver state message timeout."); } - if (driver_state_->front.heartbeat_timeout || driver_state_->rear.heartbeat_timeout) { + if (DriverStateHeartbeatTimeout()) { throw std::runtime_error("Motor controller heartbeat timeout error."); } } @@ -141,4 +150,11 @@ std::uint8_t RoboteqBattery::GetBatteryHealth(const float voltage) } } -} // namespace panther_battery +bool RoboteqBattery::DriverStateHeartbeatTimeout() +{ + return std::any_of( + driver_state_->driver_states.begin(), driver_state_->driver_states.end(), + [](const DriverStateNamedMsg & driver) { return driver.state.heartbeat_timeout; }); +} + +} // namespace husarion_ugv_battery diff --git a/panther_battery/src/battery_driver_node.cpp b/husarion_ugv_battery/src/battery_driver_node.cpp similarity index 58% rename from panther_battery/src/battery_driver_node.cpp rename to husarion_ugv_battery/src/battery_driver_node.cpp index d1ff8acd..db6a063b 100644 --- a/panther_battery/src/battery_driver_node.cpp +++ b/husarion_ugv_battery/src/battery_driver_node.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "panther_battery/battery_driver_node.hpp" +#include "husarion_ugv_battery/battery_driver_node.hpp" #include #include @@ -24,15 +24,15 @@ #include "diagnostic_updater/diagnostic_updater.hpp" #include "rclcpp/rclcpp.hpp" -#include "panther_battery/adc_data_reader.hpp" -#include "panther_battery/battery/adc_battery.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_battery/battery/roboteq_battery.hpp" -#include "panther_battery/battery_publisher/battery_publisher.hpp" -#include "panther_battery/battery_publisher/dual_battery_publisher.hpp" -#include "panther_battery/battery_publisher/single_battery_publisher.hpp" +#include "husarion_ugv_battery/adc_data_reader.hpp" +#include "husarion_ugv_battery/battery/adc_battery.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_battery/battery/roboteq_battery.hpp" +#include "husarion_ugv_battery/battery_publisher/battery_publisher.hpp" +#include "husarion_ugv_battery/battery_publisher/dual_battery_publisher.hpp" +#include "husarion_ugv_battery/battery_publisher/single_battery_publisher.hpp" -namespace panther_battery +namespace husarion_ugv_battery { BatteryDriverNode::BatteryDriverNode( @@ -41,9 +41,9 @@ BatteryDriverNode::BatteryDriverNode( { RCLCPP_INFO(this->get_logger(), "Constructing node."); - this->declare_parameter("panther_version", 1.2); - this->declare_parameter("ma_window_len/voltage", 10); - this->declare_parameter("ma_window_len/current", 10); + this->param_listener_ = + std::make_shared(this->get_node_parameters_interface()); + this->params_ = this->param_listener_->get_params(); // Running at 10 Hz battery_pub_timer_ = this->create_wall_timer( @@ -58,17 +58,14 @@ void BatteryDriverNode::Initialize() { RCLCPP_INFO(this->get_logger(), "Initializing."); - const float panther_version = this->get_parameter("panther_version").as_double(); - if (panther_version >= (1.2f - std::numeric_limits::epsilon())) { - try { - InitializeWithADCBattery(); - return; - } catch (const std::runtime_error & e) { - RCLCPP_WARN_STREAM( - this->get_logger(), "An exception occurred while initializing with ADC: " - << e.what() - << " Falling back to using Roboteq drivers to publish battery data."); - } + try { + InitializeWithADCBattery(); + return; + } catch (const std::runtime_error & e) { + RCLCPP_WARN_STREAM( + this->get_logger(), "An exception occurred while initializing with ADC: " + << e.what() + << " Falling back to using Roboteq drivers to publish battery data."); } InitializeWithRoboteqBattery(); @@ -79,22 +76,17 @@ void BatteryDriverNode::InitializeWithADCBattery() { RCLCPP_DEBUG(this->get_logger(), "Initializing with ADC data."); - this->declare_parameter("adc/device0", "/sys/bus/iio/devices/iio:device0"); - this->declare_parameter("adc/device1", "/sys/bus/iio/devices/iio:device1"); - this->declare_parameter("adc/ma_window_len/temp", 10); - this->declare_parameter("adc/ma_window_len/charge", 10); - - const std::string adc0_device_path = this->get_parameter("adc/device0").as_string(); - const std::string adc1_device_path = this->get_parameter("adc/device1").as_string(); + const std::string adc0_device_path = this->params_.adc.device0; + const std::string adc1_device_path = this->params_.adc.device1; adc0_reader_ = std::make_shared(adc0_device_path); adc1_reader_ = std::make_shared(adc1_device_path); const ADCBatteryParams battery_params = { - static_cast(this->get_parameter("ma_window_len/voltage").as_int()), - static_cast(this->get_parameter("ma_window_len/current").as_int()), - static_cast(this->get_parameter("adc/ma_window_len/temp").as_int()), - static_cast(this->get_parameter("adc/ma_window_len/charge").as_int()), + static_cast(this->params_.ma_window_len.voltage), + static_cast(this->params_.ma_window_len.current), + static_cast(this->params_.adc.ma_window_len.temp), + static_cast(this->params_.adc.ma_window_len.charge), }; battery_2_ = std::make_shared( @@ -110,7 +102,8 @@ void BatteryDriverNode::InitializeWithADCBattery() std::bind(&ADCDataReader::GetADCMeasurement, *adc0_reader_, 1, 0), std::bind(&ADCDataReader::GetADCMeasurement, *adc0_reader_, 3, 0), battery_params); battery_publisher_ = std::make_shared( - this->shared_from_this(), diagnostic_updater_, battery_1_, battery_2_); + this->shared_from_this(), diagnostic_updater_, params_.battery_timeout, battery_1_, + battery_2_); } else { battery_2_.reset(); battery_1_ = std::make_shared( @@ -122,7 +115,7 @@ void BatteryDriverNode::InitializeWithADCBattery() std::bind(&ADCDataReader::GetADCMeasurement, *adc0_reader_, 1, 0), std::bind(&ADCDataReader::GetADCMeasurement, *adc0_reader_, 3, 0), battery_params); battery_publisher_ = std::make_shared( - this->shared_from_this(), diagnostic_updater_, battery_1_); + this->shared_from_this(), diagnostic_updater_, params_.battery_timeout, battery_1_); } RCLCPP_INFO(this->get_logger(), "Initialized battery driver using ADC data."); @@ -132,22 +125,20 @@ void BatteryDriverNode::InitializeWithRoboteqBattery() { RCLCPP_DEBUG(this->get_logger(), "Initializing with Roboteq data."); - this->declare_parameter("roboteq/driver_state_timeout", 0.2); - const RoboteqBatteryParams battery_params = { - static_cast(this->get_parameter("roboteq/driver_state_timeout").as_double()), - static_cast(this->get_parameter("ma_window_len/voltage").as_int()), - static_cast(this->get_parameter("ma_window_len/current").as_int()), + static_cast(this->params_.roboteq.driver_state_timeout), + static_cast(this->params_.ma_window_len.voltage), + static_cast(this->params_.ma_window_len.current), }; - driver_state_sub_ = this->create_subscription( - "hardware/motor_controllers_state", 5, - [&](const DriverStateMsg::SharedPtr msg) { driver_state_ = msg; }); + driver_state_sub_ = this->create_subscription( + "hardware/robot_driver_state", 5, + [&](const RobotDriverStateMsg::SharedPtr msg) { driver_state_ = msg; }); battery_1_ = std::make_shared([&]() { return driver_state_; }, battery_params); battery_publisher_ = std::make_shared( - this->shared_from_this(), diagnostic_updater_, battery_1_); + this->shared_from_this(), diagnostic_updater_, this->params_.battery_timeout, battery_1_); RCLCPP_INFO(this->get_logger(), "Initialized battery driver using motor controllers data."); } @@ -161,4 +152,4 @@ void BatteryDriverNode::BatteryPubTimerCB() battery_publisher_->Publish(); } -} // namespace panther_battery +} // namespace husarion_ugv_battery diff --git a/panther_battery/src/battery_publisher/battery_publisher.cpp b/husarion_ugv_battery/src/battery_publisher/battery_publisher.cpp similarity index 90% rename from panther_battery/src/battery_publisher/battery_publisher.cpp rename to husarion_ugv_battery/src/battery_publisher/battery_publisher.cpp index e3ccb14b..4f2e9c71 100644 --- a/panther_battery/src/battery_publisher/battery_publisher.cpp +++ b/husarion_ugv_battery/src/battery_publisher/battery_publisher.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "panther_battery/battery_publisher/battery_publisher.hpp" +#include "husarion_ugv_battery/battery_publisher/battery_publisher.hpp" #include #include @@ -21,17 +21,17 @@ #include "diagnostic_updater/diagnostic_updater.hpp" #include "rclcpp/rclcpp.hpp" -namespace panther_battery +namespace husarion_ugv_battery { BatteryPublisher::BatteryPublisher( const rclcpp::Node::SharedPtr & node, - const std::shared_ptr & diagnostic_updater) -: node_(std::move(node)), diagnostic_updater_(std::move(diagnostic_updater)) + const std::shared_ptr & diagnostic_updater, + const double battery_timeout) +: node_(std::move(node)), + diagnostic_updater_(std::move(diagnostic_updater)), + battery_timeout_(battery_timeout) { - node->declare_parameter("battery_timeout", 1.0); - battery_timeout_ = node->get_parameter("battery_timeout").as_double(); - charger_connected_ = false; last_battery_info_time_ = rclcpp::Time(std::int64_t(0), RCL_ROS_TIME); @@ -49,12 +49,12 @@ void BatteryPublisher::Publish() this->Update(); last_battery_info_time_ = GetClock()->now(); } catch (const std::runtime_error & e) { - RCLCPP_ERROR_STREAM_THROTTLE( + RCLCPP_WARN_STREAM_THROTTLE( GetLogger(), *GetClock(), 1000, "An exception occurred while reading battery data: " << e.what()); diagnostic_updater_->broadcast( - diagnostic_msgs::msg::DiagnosticStatus::ERROR, + diagnostic_msgs::msg::DiagnosticStatus::WARN, "Error reading battery data: " + std::string(e.what())); } @@ -140,4 +140,4 @@ rclcpp::Clock::SharedPtr BatteryPublisher::GetClock() return std::make_shared(RCL_ROS_TIME); } -} // namespace panther_battery +} // namespace husarion_ugv_battery diff --git a/panther_battery/src/battery_publisher/dual_battery_publisher.cpp b/husarion_ugv_battery/src/battery_publisher/dual_battery_publisher.cpp similarity index 94% rename from panther_battery/src/battery_publisher/dual_battery_publisher.cpp rename to husarion_ugv_battery/src/battery_publisher/dual_battery_publisher.cpp index fba8198d..1e345280 100644 --- a/panther_battery/src/battery_publisher/dual_battery_publisher.cpp +++ b/husarion_ugv_battery/src/battery_publisher/dual_battery_publisher.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "panther_battery/battery_publisher/dual_battery_publisher.hpp" +#include "husarion_ugv_battery/battery_publisher/dual_battery_publisher.hpp" #include #include @@ -24,18 +24,19 @@ #include "sensor_msgs/msg/battery_state.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_battery/battery_publisher/battery_publisher.hpp" -#include "panther_utils/ros_utils.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_battery/battery_publisher/battery_publisher.hpp" +#include "husarion_ugv_utils/ros_utils.hpp" -namespace panther_battery +namespace husarion_ugv_battery { DualBatteryPublisher::DualBatteryPublisher( const rclcpp::Node::SharedPtr & node, const std::shared_ptr & diagnostic_updater, - const std::shared_ptr & battery_1, const std::shared_ptr & battery_2) -: BatteryPublisher(std::move(node), std::move(diagnostic_updater)), + const double battery_timeout, const std::shared_ptr & battery_1, + const std::shared_ptr & battery_2) +: BatteryPublisher(std::move(node), std::move(diagnostic_updater), battery_timeout), battery_1_(std::move(battery_1)), battery_2_(std::move(battery_2)) { @@ -172,10 +173,10 @@ ChargingStatusMsg DualBatteryPublisher::MergeChargingStatusMsgs( ChargingStatusMsg charging_status_msg; try { - panther_utils::ros::VerifyTimestampGap( + husarion_ugv_utils::ros::VerifyTimestampGap( charging_status_msg_1.header, charging_status_msg_2.header, std::chrono::seconds(1)); - charging_status_msg.header = panther_utils::ros::MergeHeaders( + charging_status_msg.header = husarion_ugv_utils::ros::MergeHeaders( charging_status_msg_1.header, charging_status_msg_2.header); } catch (const std::exception & e) { RCLCPP_ERROR_STREAM_THROTTLE( @@ -251,4 +252,4 @@ void DualBatteryPublisher::DiagnoseStatus(diagnostic_updater::DiagnosticStatusWr status.summary(diagnostic_updater::DiagnosticStatusWrapper::OK, "Battery status monitoring"); } -} // namespace panther_battery +} // namespace husarion_ugv_battery diff --git a/panther_battery/src/battery_publisher/single_battery_publisher.cpp b/husarion_ugv_battery/src/battery_publisher/single_battery_publisher.cpp similarity index 89% rename from panther_battery/src/battery_publisher/single_battery_publisher.cpp rename to husarion_ugv_battery/src/battery_publisher/single_battery_publisher.cpp index 4916e647..4fff8f68 100644 --- a/panther_battery/src/battery_publisher/single_battery_publisher.cpp +++ b/husarion_ugv_battery/src/battery_publisher/single_battery_publisher.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "panther_battery/battery_publisher/single_battery_publisher.hpp" +#include "husarion_ugv_battery/battery_publisher/single_battery_publisher.hpp" #include #include @@ -23,17 +23,18 @@ #include "sensor_msgs/msg/battery_state.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_battery/battery_publisher/battery_publisher.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_battery/battery_publisher/battery_publisher.hpp" -namespace panther_battery +namespace husarion_ugv_battery { SingleBatteryPublisher::SingleBatteryPublisher( const rclcpp::Node::SharedPtr & node, const std::shared_ptr & diagnostic_updater, - const std::shared_ptr & battery) -: BatteryPublisher(std::move(node), std::move(diagnostic_updater)), battery_(std::move(battery)) + const double battery_timeout, const std::shared_ptr & battery) +: BatteryPublisher(std::move(node), std::move(diagnostic_updater), battery_timeout), + battery_(std::move(battery)) { battery_pub_ = node->create_publisher("battery/battery_status", 5); battery_1_pub_ = node->create_publisher("_battery/battery_1_status_raw", 5); @@ -106,4 +107,4 @@ void SingleBatteryPublisher::DiagnoseStatus(diagnostic_updater::DiagnosticStatus status.summary(diagnostic_updater::DiagnosticStatusWrapper::OK, "Battery status monitoring"); } -} // namespace panther_battery +} // namespace husarion_ugv_battery diff --git a/panther_battery/src/main.cpp b/husarion_ugv_battery/src/main.cpp similarity index 86% rename from panther_battery/src/main.cpp rename to husarion_ugv_battery/src/main.cpp index b759fd33..9dc84ddf 100644 --- a/panther_battery/src/main.cpp +++ b/husarion_ugv_battery/src/main.cpp @@ -18,13 +18,14 @@ #include "rclcpp/rclcpp.hpp" -#include "panther_battery/battery_driver_node.hpp" +#include "husarion_ugv_battery/battery_driver_node.hpp" int main(int argc, char ** argv) { rclcpp::init(argc, argv); - auto battery_driver_node = std::make_shared("battery_driver"); + auto battery_driver_node = + std::make_shared("battery_driver"); try { rclcpp::spin(battery_driver_node); diff --git a/panther_battery/test/battery/test_adc_battery.cpp b/husarion_ugv_battery/test/battery/test_adc_battery.cpp similarity index 91% rename from panther_battery/test/battery/test_adc_battery.cpp rename to husarion_ugv_battery/test/battery/test_adc_battery.cpp index 986f7cdb..13a5680f 100644 --- a/panther_battery/test/battery/test_adc_battery.cpp +++ b/husarion_ugv_battery/test/battery/test_adc_battery.cpp @@ -24,8 +24,8 @@ #include "panther_msgs/msg/charging_status.hpp" -#include "panther_battery/battery/adc_battery.hpp" -#include "panther_utils/test/test_utils.hpp" +#include "husarion_ugv_battery/battery/adc_battery.hpp" +#include "husarion_ugv_utils/test/test_utils.hpp" using BatteryStateMsg = sensor_msgs::msg::BatteryState; using ChargingStatusMsg = panther_msgs::msg::ChargingStatus; @@ -54,7 +54,7 @@ class TestADCBattery : public testing::Test float battery_temp_raw_; float battery_charge_raw_; - std::unique_ptr battery_; + std::unique_ptr battery_; BatteryStateMsg battery_state_; ChargingStatusMsg charging_status_; @@ -62,8 +62,8 @@ class TestADCBattery : public testing::Test TestADCBattery::TestADCBattery() { - panther_battery::ADCBatteryParams params = {10, 10, 10, 10}; - battery_ = std::make_unique( + husarion_ugv_battery::ADCBatteryParams params = {10, 10, 10, 10}; + battery_ = std::make_unique( [&]() { return battery_voltage_raw_; }, [&]() { return battery_current_raw_; }, [&]() { return battery_temp_raw_; }, [&]() { return battery_charge_raw_; }, params); } @@ -92,8 +92,9 @@ void TestADCBattery::TestDefaultBatteryStateMsg( EXPECT_TRUE(std::isnan(battery_state_.capacity)); EXPECT_FLOAT_EQ(20.0, battery_state_.design_capacity); EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_TECHNOLOGY_LION, battery_state_.power_supply_technology); - EXPECT_TRUE(panther_utils::test_utils::CheckNaNVector(battery_state_.cell_voltage)); - EXPECT_TRUE(panther_utils::test_utils::CheckNaNVector(battery_state_.cell_temperature)); + EXPECT_TRUE(husarion_ugv_utils::test_utils::CheckNaNVector(battery_state_.cell_voltage)); + EXPECT_TRUE( + husarion_ugv_utils::test_utils::CheckNaNVector(battery_state_.cell_temperature)); EXPECT_TRUE(battery_state_.present); EXPECT_EQ("user_compartment", battery_state_.location); @@ -116,8 +117,9 @@ void TestADCBattery::TestBatteryStateMsg( EXPECT_TRUE(std::isnan(battery_state_.capacity)); EXPECT_FLOAT_EQ(20.0, battery_state_.design_capacity); EXPECT_FLOAT_EQ(expected_temp, battery_state_.temperature); - EXPECT_TRUE(panther_utils::test_utils::CheckNaNVector(battery_state_.cell_voltage)); - EXPECT_TRUE(panther_utils::test_utils::CheckNaNVector(battery_state_.cell_temperature)); + EXPECT_TRUE(husarion_ugv_utils::test_utils::CheckNaNVector(battery_state_.cell_voltage)); + EXPECT_TRUE( + husarion_ugv_utils::test_utils::CheckNaNVector(battery_state_.cell_temperature)); EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_TECHNOLOGY_LION, battery_state_.power_supply_technology); EXPECT_EQ("user_compartment", battery_state_.location); @@ -251,6 +253,11 @@ TEST_F(TestADCBattery, BatteryMsgStatusCharging) UpdateBattery(1.5, 0.01, 0.98, 0.5, true); EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_STATUS_CHARGING, battery_state_.power_supply_status); + + // Small charge, but voltage over 41.2 V + UpdateBattery(1.65, 0.01, 0.98, 0.04, true); + + EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_STATUS_CHARGING, battery_state_.power_supply_status); } TEST_F(TestADCBattery, BatteryMsgStatusNotCharging) diff --git a/panther_battery/test/battery/test_battery.cpp b/husarion_ugv_battery/test/battery/test_battery.cpp similarity index 86% rename from panther_battery/test/battery/test_battery.cpp rename to husarion_ugv_battery/test/battery/test_battery.cpp index cdbdf381..62195ca3 100644 --- a/panther_battery/test/battery/test_battery.cpp +++ b/husarion_ugv_battery/test/battery/test_battery.cpp @@ -24,13 +24,13 @@ #include "panther_msgs/msg/charging_status.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_utils/test/test_utils.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_utils/test/test_utils.hpp" using BatteryStateMsg = sensor_msgs::msg::BatteryState; using ChargingStatusMsg = panther_msgs::msg::ChargingStatus; -class BatteryWrapper : public panther_battery::Battery +class BatteryWrapper : public husarion_ugv_battery::Battery { public: BatteryWrapper() {} @@ -80,8 +80,9 @@ void TestBattery::TestDefaultBatteryStateMsg( EXPECT_TRUE(std::isnan(battery_state_.capacity)); EXPECT_FLOAT_EQ(20.0, battery_state_.design_capacity); EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_TECHNOLOGY_LION, battery_state_.power_supply_technology); - EXPECT_TRUE(panther_utils::test_utils::CheckNaNVector(battery_state_.cell_voltage)); - EXPECT_TRUE(panther_utils::test_utils::CheckNaNVector(battery_state_.cell_temperature)); + EXPECT_TRUE(husarion_ugv_utils::test_utils::CheckNaNVector(battery_state_.cell_voltage)); + EXPECT_TRUE( + husarion_ugv_utils::test_utils::CheckNaNVector(battery_state_.cell_temperature)); EXPECT_TRUE(battery_state_.present); EXPECT_EQ("user_compartment", battery_state_.location); @@ -108,10 +109,13 @@ TEST_F(TestBattery, GetErrorMsg) TEST_F(TestBattery, GetBatteryPercent) { - EXPECT_FLOAT_EQ(0.0, battery_->GetBatteryPercent(30.0f)); - EXPECT_FLOAT_EQ(0.019780006, battery_->GetBatteryPercent(32.0f)); - EXPECT_FLOAT_EQ(0.68953001, battery_->GetBatteryPercent(38.0f)); - EXPECT_FLOAT_EQ(1.0, battery_->GetBatteryPercent(42.0f)); + EXPECT_NEAR(0.0, battery_->GetBatteryPercent(30.0f), 1e-5); + EXPECT_NEAR(0.01979, battery_->GetBatteryPercent(32.0f), 1e-6); + EXPECT_NEAR(0.06822, battery_->GetBatteryPercent(34.0f), 1e-6); + EXPECT_NEAR(0.2878, battery_->GetBatteryPercent(35.5f), 1e-6); + EXPECT_NEAR(0.501, battery_->GetBatteryPercent(36.5f), 1e-6); + EXPECT_NEAR(0.68953, battery_->GetBatteryPercent(38.0f), 1e-6); + EXPECT_FLOAT_EQ(1.0, battery_->GetBatteryPercent(41.4f)); EXPECT_FLOAT_EQ(1.0, battery_->GetBatteryPercent(45.0f)); } diff --git a/panther_battery/test/battery/test_roboteq_battery.cpp b/husarion_ugv_battery/test/battery/test_roboteq_battery.cpp similarity index 73% rename from panther_battery/test/battery/test_roboteq_battery.cpp rename to husarion_ugv_battery/test/battery/test_roboteq_battery.cpp index b7059e07..26674df8 100644 --- a/panther_battery/test/battery/test_roboteq_battery.cpp +++ b/husarion_ugv_battery/test/battery/test_roboteq_battery.cpp @@ -24,27 +24,28 @@ #include "sensor_msgs/msg/battery_state.hpp" -#include "panther_msgs/msg/driver_state.hpp" +#include "panther_msgs/msg/driver_state_named.hpp" +#include "panther_msgs/msg/robot_driver_state.hpp" -#include "panther_battery/battery/roboteq_battery.hpp" -#include "panther_utils/test/test_utils.hpp" +#include "husarion_ugv_battery/battery/roboteq_battery.hpp" +#include "husarion_ugv_utils/test/test_utils.hpp" using BatteryStateMsg = sensor_msgs::msg::BatteryState; -using DriverStateMsg = panther_msgs::msg::DriverState; +using RobotDriverStateMsg = panther_msgs::msg::RobotDriverState; -class RoboteqBatteryWrapper : public panther_battery::RoboteqBattery +class RoboteqBatteryWrapper : public husarion_ugv_battery::RoboteqBattery { public: RoboteqBatteryWrapper( - const std::function & get_driver_state, - const panther_battery::RoboteqBatteryParams & params) + const std::function & get_driver_state, + const husarion_ugv_battery::RoboteqBatteryParams & params) : RoboteqBattery(get_driver_state, params) { } - void ValidateDriverStateMsg(const rclcpp::Time & header_stamp) + void ValidateRobotDriverStateMsg(const rclcpp::Time & header_stamp) { - return RoboteqBattery::ValidateDriverStateMsg(header_stamp); + return RoboteqBattery::ValidateRobotDriverStateMsg(header_stamp); } }; @@ -63,32 +64,34 @@ class TestRoboteqBattery : public testing::Test const float expected_voltage, const float expected_current, const float expected_percentage, const std::uint8_t power_supply_status, const std::uint8_t power_supply_health); - static constexpr float kDriverStateTimeout = 0.2; + static constexpr float kRobotDriverStateTimeout = 0.2; std::unique_ptr battery_; BatteryStateMsg battery_state_; - DriverStateMsg::SharedPtr driver_state_; + RobotDriverStateMsg::SharedPtr driver_state_; }; TestRoboteqBattery::TestRoboteqBattery() { - const panther_battery::RoboteqBatteryParams params = {kDriverStateTimeout, 10, 10}; + const husarion_ugv_battery::RoboteqBatteryParams params = {kRobotDriverStateTimeout, 10, 10}; battery_ = std::make_unique([&]() { return driver_state_; }, params); } void TestRoboteqBattery::UpdateBattery(const float voltage, const float current) { if (!driver_state_) { - driver_state_ = std::make_shared(); + driver_state_ = std::make_shared(); + driver_state_->driver_states.push_back(panther_msgs::msg::DriverStateNamed()); + driver_state_->driver_states.push_back(panther_msgs::msg::DriverStateNamed()); } auto stamp = rclcpp::Time(0, 0, RCL_ROS_TIME); driver_state_->header.stamp = stamp; - driver_state_->front.voltage = voltage; - driver_state_->rear.voltage = voltage; - driver_state_->front.current = current; - driver_state_->rear.current = current; + driver_state_->driver_states.at(0).state.voltage = voltage; + driver_state_->driver_states.at(1).state.voltage = voltage; + driver_state_->driver_states.at(0).state.current = current; + driver_state_->driver_states.at(1).state.current = current; battery_->Update(stamp, false); battery_state_ = battery_->GetBatteryMsg(); @@ -102,8 +105,8 @@ void TestRoboteqBattery::TestDefaultBatteryStateMsg( EXPECT_TRUE(std::isnan(battery_state_.capacity)); EXPECT_FLOAT_EQ(20.0, battery_state_.design_capacity); EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_TECHNOLOGY_LION, battery_state_.power_supply_technology); - EXPECT_TRUE(panther_utils::test_utils::CheckNaNVector(battery_state_.cell_voltage)); - EXPECT_TRUE(panther_utils::test_utils::CheckNaNVector(battery_state_.cell_temperature)); + EXPECT_TRUE(husarion_ugv_utils::test_utils::CheckNaNVector(battery_state_.cell_voltage)); + EXPECT_TRUE(husarion_ugv_utils::test_utils::CheckNaNVector(battery_state_.cell_temperature)); EXPECT_TRUE(battery_state_.present); EXPECT_EQ("user_compartment", battery_state_.location); @@ -125,8 +128,8 @@ void TestRoboteqBattery::TestBatteryStateMsg( EXPECT_TRUE(std::isnan(battery_state_.capacity)); EXPECT_TRUE(std::isnan(battery_state_.temperature)); EXPECT_FLOAT_EQ(20.0, battery_state_.design_capacity); - EXPECT_TRUE(panther_utils::test_utils::CheckNaNVector(battery_state_.cell_voltage)); - EXPECT_TRUE(panther_utils::test_utils::CheckNaNVector(battery_state_.cell_temperature)); + EXPECT_TRUE(husarion_ugv_utils::test_utils::CheckNaNVector(battery_state_.cell_voltage)); + EXPECT_TRUE(husarion_ugv_utils::test_utils::CheckNaNVector(battery_state_.cell_temperature)); EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_TECHNOLOGY_LION, battery_state_.power_supply_technology); EXPECT_EQ("user_compartment", battery_state_.location); @@ -220,31 +223,31 @@ TEST_F(TestRoboteqBattery, GetErrorMsg) EXPECT_NE("", battery_->GetErrorMsg()); } -TEST_F(TestRoboteqBattery, ValidateDriverStateMsg) +TEST_F(TestRoboteqBattery, ValidateRobotDriverStateMsg) { auto stamp = rclcpp::Time(0, 0, RCL_ROS_TIME); // Check empty driver_state msg - EXPECT_THROW(battery_->ValidateDriverStateMsg(stamp), std::runtime_error); + EXPECT_THROW(battery_->ValidateRobotDriverStateMsg(stamp), std::runtime_error); UpdateBattery(35.0f, 0.1f); - EXPECT_NO_THROW(battery_->ValidateDriverStateMsg(stamp)); + EXPECT_NO_THROW(battery_->ValidateRobotDriverStateMsg(stamp)); // Check timeout - const std::uint32_t timeout_nanoseconds = (kDriverStateTimeout + 0.05) * 1e9; + const std::uint32_t timeout_nanoseconds = (kRobotDriverStateTimeout + 0.05) * 1e9; stamp = rclcpp::Time(0, timeout_nanoseconds, RCL_ROS_TIME); - EXPECT_THROW(battery_->ValidateDriverStateMsg(stamp), std::runtime_error); + EXPECT_THROW(battery_->ValidateRobotDriverStateMsg(stamp), std::runtime_error); // Reset error stamp = rclcpp::Time(0, 0, RCL_ROS_TIME); - EXPECT_NO_THROW(battery_->ValidateDriverStateMsg(stamp)); + EXPECT_NO_THROW(battery_->ValidateRobotDriverStateMsg(stamp)); // Check heartbeat timeout error throw - driver_state_->front.heartbeat_timeout = true; - EXPECT_THROW(battery_->ValidateDriverStateMsg(stamp), std::runtime_error); - driver_state_->front.heartbeat_timeout = false; - driver_state_->rear.heartbeat_timeout = true; - EXPECT_THROW(battery_->ValidateDriverStateMsg(stamp), std::runtime_error); + driver_state_->driver_states.at(0).state.heartbeat_timeout = true; + EXPECT_THROW(battery_->ValidateRobotDriverStateMsg(stamp), std::runtime_error); + driver_state_->driver_states.at(0).state.heartbeat_timeout = false; + driver_state_->driver_states.at(1).state.heartbeat_timeout = true; + EXPECT_THROW(battery_->ValidateRobotDriverStateMsg(stamp), std::runtime_error); } int main(int argc, char ** argv) diff --git a/panther_battery/test/battery_publisher/test_battery_publisher.cpp b/husarion_ugv_battery/test/battery_publisher/test_battery_publisher.cpp similarity index 92% rename from panther_battery/test/battery_publisher/test_battery_publisher.cpp rename to husarion_ugv_battery/test/battery_publisher/test_battery_publisher.cpp index 4ed567b1..ff2fe64a 100644 --- a/panther_battery/test/battery_publisher/test_battery_publisher.cpp +++ b/husarion_ugv_battery/test/battery_publisher/test_battery_publisher.cpp @@ -24,18 +24,18 @@ #include "panther_msgs/msg/io_state.hpp" -#include "panther_battery/battery_publisher/battery_publisher.hpp" +#include "husarion_ugv_battery/battery_publisher/battery_publisher.hpp" using BatteryStateMsg = sensor_msgs::msg::BatteryState; using IOStateMsg = panther_msgs::msg::IOState; -class BatteryPublisherWrapper : public panther_battery::BatteryPublisher +class BatteryPublisherWrapper : public husarion_ugv_battery::BatteryPublisher { public: BatteryPublisherWrapper( const rclcpp::Node::SharedPtr & node, std::shared_ptr diagnostic_updater) - : panther_battery::BatteryPublisher(node, diagnostic_updater) + : husarion_ugv_battery::BatteryPublisher(node, diagnostic_updater, kBatteryTimeout) { } @@ -62,6 +62,9 @@ class BatteryPublisherWrapper : public panther_battery::BatteryPublisher { status.summary(0, ""); // Avoid unused parameter compiler warning }; + +protected: + static constexpr double kBatteryTimeout = 0.2; }; class TestBatteryPublisher : public testing::Test diff --git a/panther_battery/test/battery_publisher/test_dual_battery_publisher.cpp b/husarion_ugv_battery/test/battery_publisher/test_dual_battery_publisher.cpp similarity index 92% rename from panther_battery/test/battery_publisher/test_dual_battery_publisher.cpp rename to husarion_ugv_battery/test/battery_publisher/test_dual_battery_publisher.cpp index 0740b7fa..b14ecf63 100644 --- a/panther_battery/test/battery_publisher/test_dual_battery_publisher.cpp +++ b/husarion_ugv_battery/test/battery_publisher/test_dual_battery_publisher.cpp @@ -24,23 +24,23 @@ #include "panther_msgs/msg/charging_status.hpp" -#include "panther_battery/battery/adc_battery.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_battery/battery_publisher/dual_battery_publisher.hpp" -#include "panther_utils/test/ros_test_utils.hpp" +#include "husarion_ugv_battery/battery/adc_battery.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_battery/battery_publisher/dual_battery_publisher.hpp" +#include "husarion_ugv_utils/test/ros_test_utils.hpp" using BatteryStateMsg = sensor_msgs::msg::BatteryState; using ChargingStatusMsg = panther_msgs::msg::ChargingStatus; -class DualBatteryPublisherWrapper : public panther_battery::DualBatteryPublisher +class DualBatteryPublisherWrapper : public husarion_ugv_battery::DualBatteryPublisher { public: DualBatteryPublisherWrapper( const rclcpp::Node::SharedPtr & node, std::shared_ptr diagnostic_updater, - std::shared_ptr & battery_1, - std::shared_ptr & battery_2) - : DualBatteryPublisher(node, diagnostic_updater, battery_1, battery_2) + std::shared_ptr & battery_1, + std::shared_ptr & battery_2) + : DualBatteryPublisher(node, diagnostic_updater, kBatteryTimeout, battery_1, battery_2) { } @@ -71,6 +71,9 @@ class DualBatteryPublisherWrapper : public panther_battery::DualBatteryPublisher return DualBatteryPublisher::MergeChargingStatusMsgs( charging_status_msg_1, charging_status_msg_2); } + +private: + static constexpr double kBatteryTimeout = 0.2; }; class TestDualBatteryPublisher : public testing::Test @@ -90,8 +93,8 @@ class TestDualBatteryPublisher : public testing::Test rclcpp::Subscription::SharedPtr battery_1_sub_; rclcpp::Subscription::SharedPtr battery_2_sub_; - std::shared_ptr battery_1_; - std::shared_ptr battery_2_; + std::shared_ptr battery_1_; + std::shared_ptr battery_2_; std::shared_ptr battery_publisher_; BatteryStateMsg::SharedPtr battery_state_; BatteryStateMsg::SharedPtr battery_1_state_; @@ -100,11 +103,11 @@ class TestDualBatteryPublisher : public testing::Test TestDualBatteryPublisher::TestDualBatteryPublisher() { - panther_battery::ADCBatteryParams params = {10, 10, 10, 10}; - battery_1_ = std::make_shared( + husarion_ugv_battery::ADCBatteryParams params = {10, 10, 10, 10}; + battery_1_ = std::make_shared( [&]() { return 1.6; }, [&]() { return 0.02; }, [&]() { return 1.6; }, [&]() { return 0.4; }, params); - battery_2_ = std::make_shared( + battery_2_ = std::make_shared( [&]() { return 1.6; }, [&]() { return 0.02; }, [&]() { return 1.6; }, [&]() { return 0.4; }, params); @@ -139,13 +142,13 @@ void TestDualBatteryPublisher::TestMergeBatteryPowerSupplyStatus( TEST_F(TestDualBatteryPublisher, CorrectTopicPublished) { battery_publisher_->Publish(); - ASSERT_TRUE( - panther_utils::test_utils::WaitForMsg(node_, battery_state_, std::chrono::milliseconds(1000))); + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( + node_, battery_state_, std::chrono::milliseconds(1000))); battery_publisher_->Publish(); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( node_, battery_1_state_, std::chrono::milliseconds(1000))); battery_publisher_->Publish(); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( node_, battery_2_state_, std::chrono::milliseconds(1000))); } diff --git a/panther_battery/test/battery_publisher/test_single_battery_publisher.cpp b/husarion_ugv_battery/test/battery_publisher/test_single_battery_publisher.cpp similarity index 72% rename from panther_battery/test/battery_publisher/test_single_battery_publisher.cpp rename to husarion_ugv_battery/test/battery_publisher/test_single_battery_publisher.cpp index f7a04c3f..2afd2a37 100644 --- a/panther_battery/test/battery_publisher/test_single_battery_publisher.cpp +++ b/husarion_ugv_battery/test/battery_publisher/test_single_battery_publisher.cpp @@ -21,10 +21,10 @@ #include "sensor_msgs/msg/battery_state.hpp" -#include "panther_battery/battery/adc_battery.hpp" -#include "panther_battery/battery/battery.hpp" -#include "panther_battery/battery_publisher/single_battery_publisher.hpp" -#include "panther_utils/test/ros_test_utils.hpp" +#include "husarion_ugv_battery/battery/adc_battery.hpp" +#include "husarion_ugv_battery/battery/battery.hpp" +#include "husarion_ugv_battery/battery_publisher/single_battery_publisher.hpp" +#include "husarion_ugv_utils/test/ros_test_utils.hpp" using BatteryStateMsg = sensor_msgs::msg::BatteryState; @@ -40,16 +40,18 @@ class TestSingleBatteryPublisher : public testing::Test rclcpp::Subscription::SharedPtr battery_sub_; rclcpp::Subscription::SharedPtr battery_1_sub_; - std::shared_ptr battery_; - std::shared_ptr battery_publisher_; + std::shared_ptr battery_; + std::shared_ptr battery_publisher_; BatteryStateMsg::SharedPtr battery_state_; BatteryStateMsg::SharedPtr battery_1_state_; + + static constexpr double kBatteryTimeout = 0.2f; }; TestSingleBatteryPublisher::TestSingleBatteryPublisher() { - panther_battery::ADCBatteryParams params = {10, 10, 10, 10}; - battery_ = std::make_shared( + husarion_ugv_battery::ADCBatteryParams params = {10, 10, 10, 10}; + battery_ = std::make_shared( [&]() { return 1.6; }, [&]() { return 0.02; }, [&]() { return 1.6; }, [&]() { return 0.4; }, params); @@ -61,17 +63,17 @@ TestSingleBatteryPublisher::TestSingleBatteryPublisher() battery_1_sub_ = node_->create_subscription( "/_battery/battery_1_status_raw", 10, [&](const BatteryStateMsg::SharedPtr msg) { battery_1_state_ = msg; }); - battery_publisher_ = std::make_shared( - node_, diagnostic_updater_, battery_); + battery_publisher_ = std::make_shared( + node_, diagnostic_updater_, kBatteryTimeout, battery_); } TEST_F(TestSingleBatteryPublisher, CorrectTopicPublished) { battery_publisher_->Publish(); - ASSERT_TRUE( - panther_utils::test_utils::WaitForMsg(node_, battery_state_, std::chrono::milliseconds(1000))); + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( + node_, battery_state_, std::chrono::milliseconds(1000))); battery_publisher_->Publish(); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( node_, battery_1_state_, std::chrono::milliseconds(1000))); } diff --git a/panther_battery/test/test_adc_data_reader.cpp b/husarion_ugv_battery/test/test_adc_data_reader.cpp similarity index 92% rename from panther_battery/test/test_adc_data_reader.cpp rename to husarion_ugv_battery/test/test_adc_data_reader.cpp index c9fd3d94..bbb322bc 100644 --- a/panther_battery/test/test_adc_data_reader.cpp +++ b/husarion_ugv_battery/test/test_adc_data_reader.cpp @@ -18,7 +18,7 @@ #include "gtest/gtest.h" -#include "panther_battery/adc_data_reader.hpp" +#include "husarion_ugv_battery/adc_data_reader.hpp" class TestADCDataReader : public testing::Test { @@ -27,7 +27,7 @@ class TestADCDataReader : public testing::Test ~TestADCDataReader(); protected: - std::shared_ptr data_reader_; + std::shared_ptr data_reader_; std::filesystem::path data_file_path_; std::filesystem::path scale_file_path_; std::ofstream file_; @@ -44,7 +44,7 @@ TestADCDataReader::TestADCDataReader() WriteNumberToFile(1.0, scale_file_path_); - data_reader_ = std::make_shared(current_path); + data_reader_ = std::make_shared(current_path); } TestADCDataReader::~TestADCDataReader() diff --git a/panther_battery/test/test_battery_driver_node_adc_dual.cpp b/husarion_ugv_battery/test/test_battery_driver_node_adc_dual.cpp similarity index 88% rename from panther_battery/test/test_battery_driver_node_adc_dual.cpp rename to husarion_ugv_battery/test/test_battery_driver_node_adc_dual.cpp index 414fce6b..167035ce 100644 --- a/panther_battery/test/test_battery_driver_node_adc_dual.cpp +++ b/husarion_ugv_battery/test/test_battery_driver_node_adc_dual.cpp @@ -20,17 +20,17 @@ #include "rclcpp/rclcpp.hpp" -#include "panther_utils/test/ros_test_utils.hpp" +#include "husarion_ugv_utils/test/ros_test_utils.hpp" class TestBatteryNodeADCDual : public TestBatteryNode { public: - TestBatteryNodeADCDual() : TestBatteryNode(1.2, true) {} + TestBatteryNodeADCDual() : TestBatteryNode(true, true) {} }; TEST_F(TestBatteryNodeADCDual, BatteryValues) { - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(5000))); // This is done to check if channels of ADC readers were assigned correctly, not to verify @@ -38,8 +38,8 @@ TEST_F(TestBatteryNodeADCDual, BatteryValues) EXPECT_FLOAT_EQ(35.05957, battery_state_->voltage); EXPECT_FLOAT_EQ(2.02, battery_state_->current); EXPECT_FLOAT_EQ(26.094543, battery_state_->temperature); - EXPECT_FLOAT_EQ(0.21579468, battery_state_->percentage); - EXPECT_FLOAT_EQ(8.6317873, battery_state_->charge); + EXPECT_FLOAT_EQ(0.18720642, battery_state_->percentage); + EXPECT_FLOAT_EQ(7.4882565, battery_state_->charge); // If both batteries have the same reading values they should have equal values EXPECT_FLOAT_EQ(battery_1_state_->voltage, battery_2_state_->voltage); @@ -51,7 +51,7 @@ TEST_F(TestBatteryNodeADCDual, BatteryValues) // Change value of battery 2 reading one by one and check if corresponding values in battery 1 // stops matching WriteNumberToFile(1600, std::filesystem::path(device1_path_ / "in_voltage3_raw")); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_2_state_, std::chrono::milliseconds(1000))); EXPECT_FALSE( fabs(battery_1_state_->voltage - battery_2_state_->voltage) < @@ -67,7 +67,7 @@ TEST_F(TestBatteryNodeADCDual, BatteryValues) WriteNumberToFile(900, std::filesystem::path(device1_path_ / "in_voltage1_raw")); WriteNumberToFile(100, std::filesystem::path(device0_path_ / "in_voltage2_raw")); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_2_state_, std::chrono::milliseconds(1000))); EXPECT_FALSE( fabs(battery_1_state_->current - battery_2_state_->current) < @@ -75,7 +75,7 @@ TEST_F(TestBatteryNodeADCDual, BatteryValues) EXPECT_FLOAT_EQ(battery_1_state_->temperature, battery_2_state_->temperature); WriteNumberToFile(1000, std::filesystem::path(device0_path_ / "in_voltage0_raw")); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_2_state_, std::chrono::milliseconds(1000))); EXPECT_FALSE( fabs(battery_1_state_->temperature - battery_2_state_->temperature) < @@ -84,7 +84,7 @@ TEST_F(TestBatteryNodeADCDual, BatteryValues) TEST_F(TestBatteryNodeADCDual, BatteryTimeout) { - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(5000))); // Battery state msg should have some values @@ -98,7 +98,7 @@ TEST_F(TestBatteryNodeADCDual, BatteryTimeout) std::filesystem::remove(std::filesystem::path(device0_path_ / "in_voltage2_raw")); std::filesystem::remove(std::filesystem::path(device1_path_ / "in_voltage2_raw")); std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(1000))); // Battery state msg values should be NaN @@ -114,14 +114,14 @@ TEST_F(TestBatteryNodeADCDual, BatteryTimeout) TEST_F(TestBatteryNodeADCDual, BatteryCharging) { // Wait for node to initialize - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(5000))); // Publish charger connected state IOStateMsg io_state; io_state.charger_connected = true; io_state_pub_->publish(io_state); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(1000))); EXPECT_NE(battery_state_->power_supply_status, BatteryStateMsg::POWER_SUPPLY_STATUS_DISCHARGING); diff --git a/panther_battery/test/test_battery_driver_node_adc_single.cpp b/husarion_ugv_battery/test/test_battery_driver_node_adc_single.cpp similarity index 87% rename from panther_battery/test/test_battery_driver_node_adc_single.cpp rename to husarion_ugv_battery/test/test_battery_driver_node_adc_single.cpp index 6ddd48b3..8ad638e2 100644 --- a/panther_battery/test/test_battery_driver_node_adc_single.cpp +++ b/husarion_ugv_battery/test/test_battery_driver_node_adc_single.cpp @@ -20,12 +20,12 @@ #include "rclcpp/rclcpp.hpp" -#include "panther_utils/test/ros_test_utils.hpp" +#include "husarion_ugv_utils/test/ros_test_utils.hpp" class TestBatteryNodeADCSingle : public TestBatteryNode { public: - TestBatteryNodeADCSingle() : TestBatteryNode(1.2, false) {} + TestBatteryNodeADCSingle() : TestBatteryNode(true, false) {} }; TEST_F(TestBatteryNodeADCSingle, BatteryValues) @@ -35,7 +35,7 @@ TEST_F(TestBatteryNodeADCSingle, BatteryValues) WriteNumberToFile(1600, std::filesystem::path(device1_path_ / "in_voltage3_raw")); WriteNumberToFile(100, std::filesystem::path(device0_path_ / "in_voltage2_raw")); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(5000))); // This is done to check if channels of ADC readers were assigned correctly, not to verify @@ -43,8 +43,8 @@ TEST_F(TestBatteryNodeADCSingle, BatteryValues) EXPECT_FLOAT_EQ(35.05957, battery_state_->voltage); EXPECT_FLOAT_EQ(2.01, battery_state_->current); EXPECT_FLOAT_EQ(26.094543, battery_state_->temperature); - EXPECT_FLOAT_EQ(0.21579468, battery_state_->percentage); - EXPECT_FLOAT_EQ(4.3158937, battery_state_->charge); + EXPECT_FLOAT_EQ(0.18720642, battery_state_->percentage); + EXPECT_FLOAT_EQ(3.7441282, battery_state_->charge); // For single battery if readings stay the same values of battery_1 and battery should be the same EXPECT_FLOAT_EQ(battery_1_state_->voltage, battery_state_->voltage); @@ -56,7 +56,7 @@ TEST_F(TestBatteryNodeADCSingle, BatteryValues) TEST_F(TestBatteryNodeADCSingle, BatteryTimeout) { - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(5000))); // Battery state msg should have some values @@ -70,7 +70,7 @@ TEST_F(TestBatteryNodeADCSingle, BatteryTimeout) std::filesystem::remove(std::filesystem::path(device0_path_ / "in_voltage2_raw")); std::filesystem::remove(std::filesystem::path(device1_path_ / "in_voltage2_raw")); std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(1000))); // Battery state msg values should be NaN @@ -86,14 +86,14 @@ TEST_F(TestBatteryNodeADCSingle, BatteryTimeout) TEST_F(TestBatteryNodeADCSingle, BatteryCharging) { // Wait for node to initialize - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(5000))); // Publish charger connected state IOStateMsg io_state; io_state.charger_connected = true; io_state_pub_->publish(io_state); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(1000))); EXPECT_NE(battery_state_->power_supply_status, BatteryStateMsg::POWER_SUPPLY_STATUS_DISCHARGING); @@ -105,18 +105,18 @@ TEST_F(TestBatteryNodeADCSingle, RoboteqInitOnADCFail) std::filesystem::remove_all(device0_path_); // Wait for node to initialize - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(5000))); // Battery state status should be UNKNOWN EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_STATUS_UNKNOWN, battery_state_->power_supply_status); // Publish driver state that should update the battery message - DriverStateMsg driver_state; + RobotDriverStateMsg driver_state; driver_state.header.stamp = battery_driver_node_->get_clock()->now(); driver_state_pub_->publish(driver_state); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(1000))); // Battery state status should be different than UNKNOWN diff --git a/panther_battery/test/test_battery_driver_node_roboteq.cpp b/husarion_ugv_battery/test/test_battery_driver_node_roboteq.cpp similarity index 80% rename from panther_battery/test/test_battery_driver_node_roboteq.cpp rename to husarion_ugv_battery/test/test_battery_driver_node_roboteq.cpp index c4cf8f9c..8393b1b9 100644 --- a/panther_battery/test/test_battery_driver_node_roboteq.cpp +++ b/husarion_ugv_battery/test/test_battery_driver_node_roboteq.cpp @@ -22,18 +22,18 @@ #include "rclcpp/rclcpp.hpp" -#include "panther_utils/test/ros_test_utils.hpp" +#include "husarion_ugv_utils/test/ros_test_utils.hpp" class TestBatteryNodeRoboteq : public TestBatteryNode { public: - TestBatteryNodeRoboteq() : TestBatteryNode(1.0) {} + TestBatteryNodeRoboteq() : TestBatteryNode(false) {} }; TEST_F(TestBatteryNodeRoboteq, BatteryValues) { // Wait for node to initialize - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(5000))); // Battery state msg values should be NaN @@ -44,15 +44,17 @@ TEST_F(TestBatteryNodeRoboteq, BatteryValues) EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_STATUS_UNKNOWN, battery_state_->power_supply_status); EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_HEALTH_UNKNOWN, battery_state_->power_supply_health); - DriverStateMsg driver_state; + panther_msgs::msg::DriverStateNamed motor_controller; + motor_controller.state.voltage = 35.0f; + motor_controller.state.current = 0.1f; + + RobotDriverStateMsg driver_state; driver_state.header.stamp = battery_driver_node_->get_clock()->now(); - driver_state.front.voltage = 35.0f; - driver_state.rear.voltage = 35.0f; - driver_state.front.current = 0.1f; - driver_state.rear.current = 0.1f; + driver_state.driver_states.push_back(motor_controller); + driver_state.driver_states.push_back(motor_controller); driver_state_pub_->publish(driver_state); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(1000))); // This is done to check if values were read correctly, not to verify calculations. @@ -70,7 +72,7 @@ TEST_F(TestBatteryNodeRoboteq, BatteryValues) TEST_F(TestBatteryNodeRoboteq, BatteryTimeout) { // Wait for node to initialize - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(5000))); // Battery state msg values should be NaN @@ -82,15 +84,17 @@ TEST_F(TestBatteryNodeRoboteq, BatteryTimeout) EXPECT_EQ(BatteryStateMsg::POWER_SUPPLY_HEALTH_UNKNOWN, battery_state_->power_supply_health); // Publish some values - DriverStateMsg driver_state; + panther_msgs::msg::DriverStateNamed motor_controller; + motor_controller.state.voltage = 35.0f; + motor_controller.state.current = 0.1f; + + RobotDriverStateMsg driver_state; driver_state.header.stamp = battery_driver_node_->get_clock()->now(); - driver_state.front.voltage = 35.0f; - driver_state.rear.voltage = 35.0f; - driver_state.front.current = 0.1f; - driver_state.rear.current = 0.1f; + driver_state.driver_states.push_back(motor_controller); + driver_state.driver_states.push_back(motor_controller); driver_state_pub_->publish(driver_state); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(1000))); // Battery state msg should have some values @@ -101,7 +105,7 @@ TEST_F(TestBatteryNodeRoboteq, BatteryTimeout) // Wait for timeout std::this_thread::sleep_for(std::chrono::milliseconds(1500)); - ASSERT_TRUE(panther_utils::test_utils::WaitForMsg( + ASSERT_TRUE(husarion_ugv_utils::test_utils::WaitForMsg( battery_driver_node_, battery_state_, std::chrono::milliseconds(1000))); // Battery state msg values should be NaN diff --git a/panther_battery/test/utils/test_battery_driver_node.hpp b/husarion_ugv_battery/test/utils/test_battery_driver_node.hpp similarity index 81% rename from panther_battery/test/utils/test_battery_driver_node.hpp rename to husarion_ugv_battery/test/utils/test_battery_driver_node.hpp index 9b2385b2..7bb73c3a 100644 --- a/panther_battery/test/utils/test_battery_driver_node.hpp +++ b/husarion_ugv_battery/test/utils/test_battery_driver_node.hpp @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_BATTERY_UTILS_TEST_BATTERY_DRIVER_NODE_HPP_ -#define PANTHER_BATTERY_UTILS_TEST_BATTERY_DRIVER_NODE_HPP_ +#ifndef HUSARION_UGV_BATTERY_UTILS_TEST_BATTERY_DRIVER_NODE_HPP_ +#define HUSARION_UGV_BATTERY_UTILS_TEST_BATTERY_DRIVER_NODE_HPP_ #include #include @@ -28,19 +28,19 @@ #include "sensor_msgs/msg/battery_state.hpp" -#include "panther_msgs/msg/driver_state.hpp" #include "panther_msgs/msg/io_state.hpp" +#include "panther_msgs/msg/robot_driver_state.hpp" -#include "panther_battery/battery_driver_node.hpp" +#include "husarion_ugv_battery/battery_driver_node.hpp" using BatteryStateMsg = sensor_msgs::msg::BatteryState; -using DriverStateMsg = panther_msgs::msg::DriverState; +using RobotDriverStateMsg = panther_msgs::msg::RobotDriverState; using IOStateMsg = panther_msgs::msg::IOState; class TestBatteryNode : public testing::Test { public: - TestBatteryNode(const float panther_version = 1.2, const bool dual_battery = false); + TestBatteryNode(const bool use_adc_battery = true, const bool dual_battery = false); ~TestBatteryNode(); protected: @@ -55,26 +55,24 @@ class TestBatteryNode : public testing::Test BatteryStateMsg::SharedPtr battery_state_; BatteryStateMsg::SharedPtr battery_1_state_; BatteryStateMsg::SharedPtr battery_2_state_; - std::shared_ptr battery_driver_node_; + std::shared_ptr battery_driver_node_; rclcpp::Subscription::SharedPtr battery_sub_; rclcpp::Subscription::SharedPtr battery_1_sub_; rclcpp::Subscription::SharedPtr battery_2_sub_; rclcpp::Publisher::SharedPtr io_state_pub_; - rclcpp::Publisher::SharedPtr driver_state_pub_; + rclcpp::Publisher::SharedPtr driver_state_pub_; }; -TestBatteryNode::TestBatteryNode(const float panther_version, const bool dual_battery) +TestBatteryNode::TestBatteryNode(const bool use_adc_battery, const bool dual_battery) { std::vector params; - params.push_back(rclcpp::Parameter("panther_version", panther_version)); - if (panther_version >= 1.2 - std::numeric_limits::epsilon()) { + if (use_adc_battery) { device0_path_ = std::filesystem::path(testing::TempDir()) / kADCDevice0; device1_path_ = std::filesystem::path(testing::TempDir()) / kADCDevice1; - params.push_back(rclcpp::Parameter("adc/device0", device0_path_.string())); - params.push_back(rclcpp::Parameter("adc/device1", device1_path_.string())); - params.push_back(rclcpp::Parameter("adc/path", testing::TempDir())); + params.push_back(rclcpp::Parameter("adc.device0", device0_path_.string())); + params.push_back(rclcpp::Parameter("adc.device1", device1_path_.string())); // Create the device0 and device1 directories if they do not exist std::filesystem::create_directory(device0_path_); @@ -104,7 +102,7 @@ TestBatteryNode::TestBatteryNode(const float panther_version, const bool dual_ba rclcpp::NodeOptions options; options.parameter_overrides(params); - battery_driver_node_ = std::make_shared( + battery_driver_node_ = std::make_shared( "battery_driver", options); battery_sub_ = battery_driver_node_->create_subscription( @@ -119,8 +117,8 @@ TestBatteryNode::TestBatteryNode(const float panther_version, const bool dual_ba io_state_pub_ = battery_driver_node_->create_publisher( "hardware/io_state", rclcpp::QoS(rclcpp::KeepLast(1)).transient_local().reliable()); - driver_state_pub_ = battery_driver_node_->create_publisher( - "hardware/motor_controllers_state", 10); + driver_state_pub_ = battery_driver_node_->create_publisher( + "hardware/robot_driver_state", 10); } TestBatteryNode::~TestBatteryNode() @@ -146,4 +144,4 @@ void TestBatteryNode::WriteNumberToFile(const T number, const std::string & file } } -#endif // PANTHER_BATTERY_UTILS_TEST_BATTERY_DRIVER_NODE_HPP_ +#endif // HUSARION_UGV_BATTERY_UTILS_TEST_BATTERY_DRIVER_NODE_HPP_ diff --git a/panther_bringup/CHANGELOG.rst b/husarion_ugv_bringup/CHANGELOG.rst similarity index 100% rename from panther_bringup/CHANGELOG.rst rename to husarion_ugv_bringup/CHANGELOG.rst diff --git a/panther_bringup/CMakeLists.txt b/husarion_ugv_bringup/CMakeLists.txt similarity index 83% rename from panther_bringup/CMakeLists.txt rename to husarion_ugv_bringup/CMakeLists.txt index 79305750..6fb4694d 100644 --- a/panther_bringup/CMakeLists.txt +++ b/husarion_ugv_bringup/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10.2) -project(panther_bringup) +project(husarion_ugv_bringup) find_package(ament_cmake REQUIRED) diff --git a/panther_bringup/README.md b/husarion_ugv_bringup/README.md similarity index 87% rename from panther_bringup/README.md rename to husarion_ugv_bringup/README.md index b12b4218..3615bce3 100644 --- a/panther_bringup/README.md +++ b/husarion_ugv_bringup/README.md @@ -1,6 +1,6 @@ -# panther_bringup +# husarion_ugv_bringup -The package contains the default configuration and launch files necessary to start all the basic functionalities of the Husarion Panther robot. +The package contains the default configuration and launch files necessary to start all the basic functionalities of the Husarion UGV. ## Launch Files diff --git a/panther_bringup/launch/bringup.launch.py b/husarion_ugv_bringup/launch/bringup.launch.py similarity index 74% rename from panther_bringup/launch/bringup.launch.py rename to husarion_ugv_bringup/launch/bringup.launch.py index 96fc0445..1e542143 100644 --- a/panther_bringup/launch/bringup.launch.py +++ b/husarion_ugv_bringup/launch/bringup.launch.py @@ -14,9 +14,11 @@ # See the License for the specific language governing permissions and # limitations under the License. + +from husarion_ugv_utils.messages import welcome_msg from launch import LaunchDescription from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription, TimerAction -from launch.conditions import IfCondition, UnlessCondition +from launch.conditions import UnlessCondition from launch.launch_description_sources import PythonLaunchDescriptionSource from launch.substitutions import ( EnvironmentVariable, @@ -24,7 +26,6 @@ PathJoinSubstitution, ) from launch_ros.substitutions import FindPackageShare -from panther_utils.welcomeMsg import welcomeMsg def generate_launch_description(): @@ -43,22 +44,15 @@ def generate_launch_description(): description="Add namespace to all launched nodes.", ) - use_ekf = LaunchConfiguration("use_ekf") - declare_use_ekf_arg = DeclareLaunchArgument( - "use_ekf", - default_value="True", - description="Enable or disable EKF.", - choices=["True", "true", "False", "false"], - ) - - serial_no = EnvironmentVariable(name="PANTHER_SERIAL_NO", default_value="----") - panther_version = EnvironmentVariable(name="PANTHER_ROBOT_VERSION", default_value="1.0") - welcome_msg = welcomeMsg(serial_no, panther_version) + robot_model_name = EnvironmentVariable(name="ROBOT_MODEL_NAME", default_value="panther") + robot_serial_no = EnvironmentVariable(name="ROBOT_SERIAL_NO", default_value="----") + robot_version = EnvironmentVariable(name="ROBOT_VERSION", default_value="1.0") + welcome_info = welcome_msg(robot_model_name, robot_serial_no, robot_version) controller_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource( PathJoinSubstitution( - [FindPackageShare("panther_controller"), "launch", "controller.launch.py"] + [FindPackageShare("husarion_ugv_controller"), "launch", "controller.launch.py"] ) ), launch_arguments={"namespace": namespace}.items(), @@ -68,7 +62,7 @@ def generate_launch_description(): PythonLaunchDescriptionSource( PathJoinSubstitution( [ - FindPackageShare("panther_diagnostics"), + FindPackageShare("husarion_ugv_diagnostics"), "launch", "system_monitor.launch.py", ] @@ -80,7 +74,7 @@ def generate_launch_description(): lights_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource( PathJoinSubstitution( - [FindPackageShare("panther_lights"), "launch", "lights.launch.py"] + [FindPackageShare("husarion_ugv_lights"), "launch", "lights.launch.py"] ) ), launch_arguments={"namespace": namespace}.items(), @@ -89,7 +83,7 @@ def generate_launch_description(): battery_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource( PathJoinSubstitution( - [FindPackageShare("panther_battery"), "launch", "battery.launch.py"] + [FindPackageShare("husarion_ugv_battery"), "launch", "battery.launch.py"] ), ), launch_arguments={"namespace": namespace}.items(), @@ -98,17 +92,16 @@ def generate_launch_description(): ekf_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource( PathJoinSubstitution( - [FindPackageShare("panther_localization"), "launch", "localization.launch.py"] + [FindPackageShare("husarion_ugv_localization"), "launch", "localization.launch.py"] ) ), launch_arguments={"namespace": namespace}.items(), - condition=IfCondition(use_ekf), ) manager_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource( PathJoinSubstitution( - [FindPackageShare("panther_manager"), "launch", "manager.launch.py"] + [FindPackageShare("husarion_ugv_manager"), "launch", "manager.launch.py"] ) ), condition=UnlessCondition(disable_manager), @@ -128,8 +121,7 @@ def generate_launch_description(): actions = [ declare_disable_manager_arg, declare_namespace_arg, - declare_use_ekf_arg, - welcome_msg, + welcome_info, controller_launch, system_monitor_launch, delayed_action, diff --git a/panther_bringup/package.xml b/husarion_ugv_bringup/package.xml similarity index 81% rename from panther_bringup/package.xml rename to husarion_ugv_bringup/package.xml index ebd80a4e..9bc144d1 100644 --- a/panther_bringup/package.xml +++ b/husarion_ugv_bringup/package.xml @@ -1,9 +1,9 @@ - panther_bringup + husarion_ugv_bringup 2.1.2 - Default launch files and configuration used to start Husarion Panther robot + Default launch files and configuration used to start Husarion UGV Husarion Apache License 2.0 @@ -15,15 +15,15 @@ ament_cmake + husarion_ugv_battery + husarion_ugv_controller + husarion_ugv_diagnostics + husarion_ugv_lights + husarion_ugv_localization + husarion_ugv_manager + husarion_ugv_utils launch launch_ros - panther_battery - panther_controller - panther_diagnostics - panther_lights - panther_localization - panther_manager - panther_utils ament_cmake diff --git a/panther_controller/CHANGELOG.rst b/husarion_ugv_controller/CHANGELOG.rst similarity index 100% rename from panther_controller/CHANGELOG.rst rename to husarion_ugv_controller/CHANGELOG.rst diff --git a/panther_localization/CMakeLists.txt b/husarion_ugv_controller/CMakeLists.txt similarity index 82% rename from panther_localization/CMakeLists.txt rename to husarion_ugv_controller/CMakeLists.txt index 33da28a6..9cf8423a 100644 --- a/panther_localization/CMakeLists.txt +++ b/husarion_ugv_controller/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10.2) -project(panther_localization) +project(husarion_ugv_controller) find_package(ament_cmake REQUIRED) diff --git a/husarion_ugv_controller/CONFIGURATION.md b/husarion_ugv_controller/CONFIGURATION.md new file mode 100644 index 00000000..01a40d15 --- /dev/null +++ b/husarion_ugv_controller/CONFIGURATION.md @@ -0,0 +1,9 @@ +# husarion_ugv_controller + +## Changing Velocity Smoothing Parameters + +The default drive controller is based on [diff_drive_controller](https://control.ros.org/master/doc/ros2_controllers/diff_drive_controller/doc/userdoc.html) from [ros2 control](https://control.ros.org/master/index.html) or [mecanum_drive_controller](https://github.com/husarion/husarion_controllers/tree/main/mecanum_drive_controller). This controller can be customized, among others: by modifying the robot's dynamic parameters (e.g. smooth the speed or limit the robot's speed and acceleration). Its parameters can be found in the [husarion_ugv_controller](https://github.com/husarion/panther_ros/tree/ros2-devel/husarion_ugv_controller/config). By default, these values correspond to the upper limits of the robot's velocities and accelerations. + +## Changing Wheel Type + +Changing wheel types is possible and can be done for both the real robot and the simulation. By default, three types of wheels are supported using the launch argument `wheel_type`. If you want to use custom wheels, all you need to do is point to the new wheel and controller configuration files using the `wheel_config_path` and `controller_config_path` parameters. These files should be based on the default files, i.e. [WH01_controller.yaml](./config/WH01_controller.yaml) and [WH01.yaml](../panther_description/config/WH01.yaml). diff --git a/panther_controller/README.md b/husarion_ugv_controller/README.md similarity index 96% rename from panther_controller/README.md rename to husarion_ugv_controller/README.md index ac600dc7..509a5e4e 100644 --- a/panther_controller/README.md +++ b/husarion_ugv_controller/README.md @@ -1,6 +1,6 @@ -# panther_controller +# husarion_ugv_controller -The package contains the default configuration and launch files necessary to start all the basic functionalities of the Husarion Panther robot. +The package contains the default configuration and launch files necessary to start all the basic functionalities of the Husarion UGV. ## Launch Files diff --git a/panther_controller/config/WH01_controller.yaml b/husarion_ugv_controller/config/WH01_controller.yaml similarity index 99% rename from panther_controller/config/WH01_controller.yaml rename to husarion_ugv_controller/config/WH01_controller.yaml index 4187aa50..da21d73e 100644 --- a/panther_controller/config/WH01_controller.yaml +++ b/husarion_ugv_controller/config/WH01_controller.yaml @@ -55,7 +55,7 @@ enable_odom_tf: false - cmd_vel_timeout: 0.5 + cmd_vel_timeout: 0.2 #publish_limited_velocity: true use_stamped_vel: false diff --git a/panther_controller/config/WH02_controller.yaml b/husarion_ugv_controller/config/WH02_controller.yaml similarity index 99% rename from panther_controller/config/WH02_controller.yaml rename to husarion_ugv_controller/config/WH02_controller.yaml index 6d109509..0e6e8ee5 100644 --- a/panther_controller/config/WH02_controller.yaml +++ b/husarion_ugv_controller/config/WH02_controller.yaml @@ -56,7 +56,7 @@ enable_odom_tf: false - cmd_vel_timeout: 0.5 + cmd_vel_timeout: 0.2 #publish_limited_velocity: true use_stamped_vel: false diff --git a/panther_controller/config/WH04_controller.yaml b/husarion_ugv_controller/config/WH04_controller.yaml similarity index 98% rename from panther_controller/config/WH04_controller.yaml rename to husarion_ugv_controller/config/WH04_controller.yaml index 25987350..2ae5cb34 100644 --- a/panther_controller/config/WH04_controller.yaml +++ b/husarion_ugv_controller/config/WH04_controller.yaml @@ -32,7 +32,7 @@ wheel_separation: 0.616 wheel_radius: 0.1016 - # todo: check it for panther + # TODO: check it # For skid drive kinematics it will act as ICR coefficient, kinematic model with ICR # coefficient isn't totally accurate and this coefficient can differ for various ground types wheel_separation_multiplier: 1.0 @@ -56,7 +56,7 @@ enable_odom_tf: false - cmd_vel_timeout: 0.5 + cmd_vel_timeout: 0.2 #publish_limited_velocity: true use_stamped_vel: false diff --git a/husarion_ugv_controller/config/WH05_controller.yaml b/husarion_ugv_controller/config/WH05_controller.yaml new file mode 100644 index 00000000..e9cfd598 --- /dev/null +++ b/husarion_ugv_controller/config/WH05_controller.yaml @@ -0,0 +1,84 @@ +/**: + controller_manager: + ros__parameters: + update_rate: 100 + + joint_state_broadcaster: + type: joint_state_broadcaster/JointStateBroadcaster + drive_controller: + type: diff_drive_controller/DiffDriveController + imu_broadcaster: + type: imu_sensor_broadcaster/IMUSensorBroadcaster + + # IMU specification: https://www.phidgets.com/?tier=3&catid=10&pcid=8&prodid=1025#Tab_Specifications + imu_broadcaster: + ros__parameters: + use_namespace_as_sensor_name_prefix: true + + sensor_name: imu + frame_id: imu_link + # orientation_stddev: 4.3e-2 rad determined experimentally + static_covariance_orientation: [1.8e-3, 0.0, 0.0, 0.0, 1.8e-3, 0.0, 0.0, 0.0, 1.8e-3] + # angular_velocity_stdev: 0.59 deg/s (0.01 rad/s) gyroscope white noise sigma, according to the manual + static_covariance_angular_velocity: [1.0e-4, 0.0, 0.0, 0.0, 1.0e-4, 0.0, 0.0, 0.0, 1.0e-4] + # linear_acceleration_stdev: 2.8 mg (0.0275 m/s^2) accelerometer white noise sigma, according to the manual + static_covariance_linear_acceleration: [7.6e-4, 0.0, 0.0, 0.0, 7.6e-4, 0.0, 0.0, 0.0, 7.6e-4] + + drive_controller: + ros__parameters: + left_wheel_names: [fl_wheel_joint, rl_wheel_joint] + right_wheel_names: [fr_wheel_joint, rr_wheel_joint] + + wheel_separation: 0.45 + wheel_radius: 0.1348 + + # For skid drive kinematics it will act as ICR coefficient, kinematic model with ICR + # coefficient isn't totally accurate and this coefficient can differ for various ground types + wheel_separation_multiplier: 1.5 + + left_wheel_radius_multiplier: 1.0 + right_wheel_radius_multiplier: 1.0 + + publish_rate: 100.0 + odom_frame_id: odom + base_frame_id: base_link + twist_covariance_diagonal: [5.4e-5, 5.4e-5, 0.0, 0.0, 0.0, 1.9e-4] # Values measured experimentally + + # Whether to use feedback or commands for odometry calculations + open_loop: false + + # Update odometry from velocity + # in sensor fusion only velocity is used and with this setting it is more accurate + position_feedback: false + # velocity computation filtering + velocity_rolling_window_size: 1 + + enable_odom_tf: false + + cmd_vel_timeout: 0.2 + #publish_limited_velocity: true + use_stamped_vel: false + + # Velocity and acceleration limits + # Whenever a min_* is unspecified, default to -max_* + linear: + x: + has_velocity_limits: true + has_acceleration_limits: true + has_jerk_limits: false + max_velocity: 1.5 # m/s + # min_velocity - When unspecified `min_velocity=-max_velocity` + max_acceleration: 2.1 # m/s^2 + # min_acceleration - When unspecified, `min_acceleration=-max_acceleration` + max_jerk: 0.0 # m/s^3 + + angular: + z: + has_velocity_limits: true + has_acceleration_limits: true + has_jerk_limits: false + max_velocity: 4.0 # rad/s + # min_velocity - When unspecified `min_velocity=-max_velocity` + max_acceleration: 5.74 # rad/s^2 + # min_acceleration - When unspecified, `min_acceleration=-max_acceleration` + max_jerk: 0.0 # rad/s^3 diff --git a/panther_controller/launch/controller.launch.py b/husarion_ugv_controller/launch/controller.launch.py similarity index 79% rename from panther_controller/launch/controller.launch.py rename to husarion_ugv_controller/launch/controller.launch.py index 0ad64e58..843bbbc6 100644 --- a/panther_controller/launch/controller.launch.py +++ b/husarion_ugv_controller/launch/controller.launch.py @@ -34,6 +34,21 @@ def generate_launch_description(): + husarion_ugv_controller_common_dir = PathJoinSubstitution( + ["/config", "husarion_ugv_controller"] + ) + + robot_model = LaunchConfiguration("robot_model") + robot_description_pkg = PythonExpression(["'", robot_model, "_description'"]) + robot_description_common_dir = PathJoinSubstitution(["/config", robot_description_pkg]) + + declare_robot_model_arg = DeclareLaunchArgument( + "robot_model", + default_value=EnvironmentVariable(name="ROBOT_MODEL_NAME", default_value="panther"), + description="Specify robot model", + choices=["lynx", "panther"], + ) + battery_config_path = LaunchConfiguration("battery_config_path") declare_battery_config_path_arg = DeclareLaunchArgument( "battery_config_path", @@ -48,32 +63,30 @@ def generate_launch_description(): declare_components_config_path_arg = DeclareLaunchArgument( "components_config_path", default_value=PathJoinSubstitution( - [FindPackageShare("panther_description"), "config", "components.yaml"] + [robot_description_common_dir, "config", "components.yaml"] ), description=( "Additional components configuration file. Components described in this file " - "are dynamically included in Panther's urdf." - "Panther options are described here " + "are dynamically included in robot's URDF." + "Available options are described in the manual: " "https://husarion.com/manuals/panther/panther-options/" ), ) - wheel_type = LaunchConfiguration( - "wheel_type" - ) # wheel_type must be before controller_config_path + wheel_type = LaunchConfiguration("wheel_type") controller_config_path = LaunchConfiguration("controller_config_path") declare_controller_config_path_arg = DeclareLaunchArgument( "controller_config_path", default_value=PathJoinSubstitution( [ - FindPackageShare("panther_controller"), + husarion_ugv_controller_common_dir, "config", PythonExpression(["'", wheel_type, "_controller.yaml'"]), ] ), description=( "Path to controller configuration file. By default, it is located in" - " 'panther_controller/config/{wheel_type}_controller.yaml'. You can also specify" + " 'husarion_ugv_controller/config/{wheel_type}_controller.yaml'. You can also specify" " the path to your custom controller configuration file here. " ), ) @@ -96,7 +109,7 @@ def generate_launch_description(): choices=["True", "true", "False", "false"], ) - wheel_config_path = LaunchConfiguration("wheel_config_path") + use_sim = LaunchConfiguration("use_sim") declare_use_sim_arg = DeclareLaunchArgument( "use_sim", default_value="False", @@ -104,11 +117,12 @@ def generate_launch_description(): choices=["True", "true", "False", "false"], ) + wheel_config_path = LaunchConfiguration("wheel_config_path") declare_wheel_config_path_arg = DeclareLaunchArgument( "wheel_config_path", default_value=PathJoinSubstitution( [ - FindPackageShare("panther_description"), + FindPackageShare(robot_description_pkg), "config", PythonExpression(["'", wheel_type, ".yaml'"]), ] @@ -120,33 +134,37 @@ def generate_launch_description(): ), ) - use_sim = LaunchConfiguration("use_sim") + default_wheel_type = {"lynx": "WH05", "panther": "WH01"} declare_wheel_type_arg = DeclareLaunchArgument( "wheel_type", - default_value="WH01", + default_value=PythonExpression([f"{default_wheel_type}['", robot_model, "']"]), description=( - "Type of wheel. If you choose a value from the preset options ('WH01', 'WH02'," - " 'WH04'), you can ignore the 'wheel_config_path' and 'controller_config_path'" - " parameters. For custom wheels, please define these parameters to point to files that" - " accurately describe the custom wheels." + "Specify the wheel type. If the selected wheel type is not 'custom', " + "the 'wheel_config_path' and 'controller_config_path' arguments will be " + "automatically adjusted and can be omitted." ), - choices=["WH01", "WH02", "WH04", "custom"], + choices=["WH01", "WH02", "WH04", "WH05", "custom"], ) # Get URDF via xacro + robot_description_file = PythonExpression(["'", robot_model, ".urdf.xacro'"]) + imu_pos_x = os.environ.get("ROBOT_IMU_LOCALIZATION_X", "0.168") + imu_pos_y = os.environ.get("ROBOT_IMU_LOCALIZATION_Y", "0.028") + imu_pos_z = os.environ.get("ROBOT_IMU_LOCALIZATION_Z", "0.083") + imu_rot_r = os.environ.get("ROBOT_IMU_ORIENTATION_R", "3.14") + imu_rot_p = os.environ.get("ROBOT_IMU_ORIENTATION_P", "-1.57") + imu_rot_y = os.environ.get("ROBOT_IMU_ORIENTATION_Y", "0.0") robot_description_content = Command( [ PathJoinSubstitution([FindExecutable(name="xacro")]), " ", PathJoinSubstitution( [ - FindPackageShare("panther_description"), + FindPackageShare(robot_description_pkg), "urdf", - "panther.urdf.xacro", + robot_description_file, ] ), - " panther_version:=", - os.environ.get("PANTHER_ROBOT_VERSION", "1.0"), " use_sim:=", use_sim, " wheel_config_file:=", @@ -156,9 +174,9 @@ def generate_launch_description(): " battery_config_file:=", battery_config_path, " imu_xyz:=", - f"\"{os.environ.get('PANTHER_IMU_LOCALIZATION_X', '0.168')} {os.environ.get('PANTHER_IMU_LOCALIZATION_Y', '0.028')} {os.environ.get('PANTHER_IMU_LOCALIZATION_Z', '0.083')}\"", + f"'{imu_pos_x} {imu_pos_y} {imu_pos_z}'", " imu_rpy:=", - f"\"{os.environ.get('PANTHER_IMU_ORIENTATION_R', '3.14')} {os.environ.get('PANTHER_IMU_ORIENTATION_P', '-1.57')} {os.environ.get('PANTHER_IMU_ORIENTATION_Y', '0.0')}\"", + f"'{imu_rot_r} {imu_rot_p} {imu_rot_y}'", " namespace:=", namespace, " components_config_path:=", @@ -186,7 +204,7 @@ def generate_launch_description(): ("hardware_controller/fan_enable", "hardware/fan_enable"), ("hardware_controller/io_state", "hardware/io_state"), ("hardware_controller/led_control_enable", "hardware/led_control_enable"), - ("hardware_controller/motor_controllers_state", "hardware/motor_controllers_state"), + ("hardware_controller/robot_driver_state", "hardware/robot_driver_state"), ("hardware_controller/motor_power_enable", "hardware/motor_power_enable"), ("imu_broadcaster/imu", "imu/data"), ("imu_broadcaster/transition_event", "_imu_broadcaster/transition_event"), @@ -271,7 +289,8 @@ def generate_launch_description(): actions = [ declare_battery_config_path_arg, - declare_wheel_type_arg, # wheel_type must be before controller_config_path + declare_robot_model_arg, # robot_model is used by wheel_type + declare_wheel_type_arg, # wheel_type is used by controller_config_path declare_components_config_path_arg, declare_controller_config_path_arg, declare_namespace_arg, diff --git a/panther_controller/package.xml b/husarion_ugv_controller/package.xml similarity index 86% rename from panther_controller/package.xml rename to husarion_ugv_controller/package.xml index 5a72a325..591bd912 100644 --- a/panther_controller/package.xml +++ b/husarion_ugv_controller/package.xml @@ -1,9 +1,9 @@ - panther_controller + husarion_ugv_controller 2.1.2 - ros2 controllers configuration for Panther + ros2 controllers configuration for Husarion UGV Husarion Apache License 2.0 @@ -18,13 +18,14 @@ controller_manager diff_drive_controller + husarion_ugv_hardware_interfaces imu_sensor_broadcaster joint_state_broadcaster launch launch_ros + lynx_description mecanum_drive_controller panther_description - panther_hardware_interfaces robot_state_publisher xacro diff --git a/panther_diagnostics/CHANGELOG.rst b/husarion_ugv_diagnostics/CHANGELOG.rst similarity index 100% rename from panther_diagnostics/CHANGELOG.rst rename to husarion_ugv_diagnostics/CHANGELOG.rst diff --git a/panther_diagnostics/CMakeLists.txt b/husarion_ugv_diagnostics/CMakeLists.txt similarity index 97% rename from panther_diagnostics/CMakeLists.txt rename to husarion_ugv_diagnostics/CMakeLists.txt index 8794efbe..64b9751d 100644 --- a/panther_diagnostics/CMakeLists.txt +++ b/husarion_ugv_diagnostics/CMakeLists.txt @@ -8,7 +8,7 @@ if(USE_SUPERBUILD) include(cmake/SuperBuild.cmake) return() else() - project(panther_diagnostics) + project(husarion_ugv_diagnostics) endif() if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") @@ -21,7 +21,7 @@ set(PACKAGE_DEPENDENCIES diagnostic_updater generate_parameter_library panther_msgs - panther_utils + husarion_ugv_utils PkgConfig rclcpp std_msgs) diff --git a/panther_diagnostics/README.md b/husarion_ugv_diagnostics/README.md similarity index 95% rename from panther_diagnostics/README.md rename to husarion_ugv_diagnostics/README.md index d3e213bb..02d37021 100644 --- a/panther_diagnostics/README.md +++ b/husarion_ugv_diagnostics/README.md @@ -1,6 +1,6 @@ -# panther_diagnostics +# husarion_ugv_diagnostics -Package containing nodes monitoring and publishing the Built-in Computer status of Husarion Panther robot. +Package containing nodes monitoring and publishing the Built-in Computer status of Husarion UGV. ## Launch Files diff --git a/panther_diagnostics/cmake/SuperBuild.cmake b/husarion_ugv_diagnostics/cmake/SuperBuild.cmake similarity index 97% rename from panther_diagnostics/cmake/SuperBuild.cmake rename to husarion_ugv_diagnostics/cmake/SuperBuild.cmake index 4370b4cd..83fdadbb 100644 --- a/panther_diagnostics/cmake/SuperBuild.cmake +++ b/husarion_ugv_diagnostics/cmake/SuperBuild.cmake @@ -30,7 +30,7 @@ ExternalProject_Add( BUILD_IN_SOURCE 1) ExternalProject_Add( - ep_panther_diagnostics + ep_husarion_ugv_diagnostics DEPENDS ${DEPENDENCIES} SOURCE_DIR ${PROJECT_SOURCE_DIR} CMAKE_ARGS -DUSE_SUPERBUILD=OFF diff --git a/panther_diagnostics/config/system_monitor.yaml b/husarion_ugv_diagnostics/config/system_monitor.yaml similarity index 100% rename from panther_diagnostics/config/system_monitor.yaml rename to husarion_ugv_diagnostics/config/system_monitor.yaml diff --git a/panther_diagnostics/include/panther_diagnostics/filesystem.hpp b/husarion_ugv_diagnostics/include/husarion_ugv_diagnostics/filesystem.hpp similarity index 93% rename from panther_diagnostics/include/panther_diagnostics/filesystem.hpp rename to husarion_ugv_diagnostics/include/husarion_ugv_diagnostics/filesystem.hpp index fa2291d6..17825312 100644 --- a/panther_diagnostics/include/panther_diagnostics/filesystem.hpp +++ b/husarion_ugv_diagnostics/include/husarion_ugv_diagnostics/filesystem.hpp @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_DIAGNOSTICS_FILESYSTEM_HPP_ -#define PANTHER_DIAGNOSTICS_FILESYSTEM_HPP_ +#ifndef HUSARION_UGV_DIAGNOSTICS_FILESYSTEM_HPP_ +#define HUSARION_UGV_DIAGNOSTICS_FILESYSTEM_HPP_ #include #include -namespace panther_diagnostics +namespace husarion_ugv_diagnostics { /** @@ -110,6 +110,6 @@ class Filesystem : public FilesystemInterface } }; -} // namespace panther_diagnostics +} // namespace husarion_ugv_diagnostics -#endif // PANTHER_DIAGNOSTICS_FILESYSTEM_HPP_ +#endif // HUSARION_UGV_DIAGNOSTICS_FILESYSTEM_HPP_ diff --git a/panther_diagnostics/include/panther_diagnostics/system_monitor_node.hpp b/husarion_ugv_diagnostics/include/husarion_ugv_diagnostics/system_monitor_node.hpp similarity index 87% rename from panther_diagnostics/include/panther_diagnostics/system_monitor_node.hpp rename to husarion_ugv_diagnostics/include/husarion_ugv_diagnostics/system_monitor_node.hpp index c840a246..0532822f 100644 --- a/panther_diagnostics/include/panther_diagnostics/system_monitor_node.hpp +++ b/husarion_ugv_diagnostics/include/husarion_ugv_diagnostics/system_monitor_node.hpp @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_DIAGNOSTICS_SYSTEM_MONITOR_NODE_HPP_ -#define PANTHER_DIAGNOSTICS_SYSTEM_MONITOR_NODE_HPP_ +#ifndef HUSARION_UGV_DIAGNOSTICS_SYSTEM_MONITOR_NODE_HPP_ +#define HUSARION_UGV_DIAGNOSTICS_SYSTEM_MONITOR_NODE_HPP_ #include @@ -24,12 +24,12 @@ #include "system_monitor_parameters.hpp" -#include "panther_diagnostics/filesystem.hpp" -#include "panther_diagnostics/types.hpp" +#include "husarion_ugv_diagnostics/filesystem.hpp" +#include "husarion_ugv_diagnostics/types.hpp" using namespace std::chrono_literals; -namespace panther_diagnostics +namespace husarion_ugv_diagnostics { class SystemMonitorNode : public rclcpp::Node @@ -81,5 +81,5 @@ class SystemMonitorNode : public rclcpp::Node static constexpr char kTemperatureInfoFilename[] = "/sys/class/thermal/thermal_zone0/temp"; static constexpr char kRootDirectory[] = "/"; }; -} // namespace panther_diagnostics -#endif // PANTHER_DIAGNOSTICS_SYSTEM_MONITOR_NODE_HPP_ +} // namespace husarion_ugv_diagnostics +#endif // HUSARION_UGV_DIAGNOSTICS_SYSTEM_MONITOR_NODE_HPP_ diff --git a/panther_diagnostics/include/panther_diagnostics/types.hpp b/husarion_ugv_diagnostics/include/husarion_ugv_diagnostics/types.hpp similarity index 82% rename from panther_diagnostics/include/panther_diagnostics/types.hpp rename to husarion_ugv_diagnostics/include/husarion_ugv_diagnostics/types.hpp index 1ed2c88c..4108b56d 100644 --- a/panther_diagnostics/include/panther_diagnostics/types.hpp +++ b/husarion_ugv_diagnostics/include/husarion_ugv_diagnostics/types.hpp @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef PANTHER_DIAGNOSTICS_TYPES_HPP_ -#define PANTHER_DIAGNOSTICS_TYPES_HPP_ +#ifndef HUSARION_UGV_DIAGNOSTICS_TYPES_HPP_ +#define HUSARION_UGV_DIAGNOSTICS_TYPES_HPP_ #include -namespace panther_diagnostics +namespace husarion_ugv_diagnostics { /** @@ -35,6 +35,6 @@ struct SystemStatus float disk_usage; }; -} // namespace panther_diagnostics +} // namespace husarion_ugv_diagnostics -#endif // PANTHER_DIAGNOSTICS_TYPES_HPP_ +#endif // HUSARION_UGV_DIAGNOSTICS_TYPES_HPP_ diff --git a/panther_diagnostics/launch/system_monitor.launch.py b/husarion_ugv_diagnostics/launch/system_monitor.launch.py similarity index 97% rename from panther_diagnostics/launch/system_monitor.launch.py rename to husarion_ugv_diagnostics/launch/system_monitor.launch.py index e2d2ab70..34a82815 100644 --- a/panther_diagnostics/launch/system_monitor.launch.py +++ b/husarion_ugv_diagnostics/launch/system_monitor.launch.py @@ -29,7 +29,7 @@ def generate_launch_description(): ) system_monitor_node = Node( - package="panther_diagnostics", + package="husarion_ugv_diagnostics", executable="system_monitor_node", name="system_monitor", namespace=namespace, diff --git a/panther_diagnostics/package.xml b/husarion_ugv_diagnostics/package.xml similarity index 87% rename from panther_diagnostics/package.xml rename to husarion_ugv_diagnostics/package.xml index f51b357e..c7980707 100644 --- a/panther_diagnostics/package.xml +++ b/husarion_ugv_diagnostics/package.xml @@ -1,9 +1,9 @@ - panther_diagnostics + husarion_ugv_diagnostics 2.1.2 - Package for diagnosting usage of OS on the Panther Robot + Package for diagnosting usage of OS on the Husarion UGV robot Husarion Apache License 2.0 @@ -20,8 +20,8 @@ diagnostic_msgs diagnostic_updater generate_parameter_library + husarion_ugv_utils panther_msgs - panther_utils rclcpp std_msgs diff --git a/panther_diagnostics/src/main.cpp b/husarion_ugv_diagnostics/src/main.cpp similarity index 80% rename from panther_diagnostics/src/main.cpp rename to husarion_ugv_diagnostics/src/main.cpp index 8d09517f..61cb38cc 100644 --- a/panther_diagnostics/src/main.cpp +++ b/husarion_ugv_diagnostics/src/main.cpp @@ -18,15 +18,15 @@ #include -#include "panther_diagnostics/filesystem.hpp" -#include "panther_diagnostics/system_monitor_node.hpp" +#include "husarion_ugv_diagnostics/filesystem.hpp" +#include "husarion_ugv_diagnostics/system_monitor_node.hpp" int main(int argc, char ** argv) { rclcpp::init(argc, argv); - auto filesystem = std::make_shared(); - auto system_monitor_node = std::make_shared( + auto filesystem = std::make_shared(); + auto system_monitor_node = std::make_shared( "system_monitor", filesystem); try { diff --git a/panther_diagnostics/src/system_monitor_node.cpp b/husarion_ugv_diagnostics/src/system_monitor_node.cpp similarity index 89% rename from panther_diagnostics/src/system_monitor_node.cpp rename to husarion_ugv_diagnostics/src/system_monitor_node.cpp index bc921a75..f25bcbe3 100644 --- a/panther_diagnostics/src/system_monitor_node.cpp +++ b/husarion_ugv_diagnostics/src/system_monitor_node.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "panther_diagnostics/system_monitor_node.hpp" +#include "husarion_ugv_diagnostics/system_monitor_node.hpp" #include #include @@ -24,13 +24,13 @@ #include "panther_msgs/msg/system_status.hpp" -#include "panther_utils/common_utilities.hpp" -#include "panther_utils/ros_utils.hpp" +#include "husarion_ugv_utils/common_utilities.hpp" +#include "husarion_ugv_utils/ros_utils.hpp" -#include "panther_diagnostics/filesystem.hpp" -#include "panther_diagnostics/types.hpp" +#include "husarion_ugv_diagnostics/filesystem.hpp" +#include "husarion_ugv_diagnostics/types.hpp" -namespace panther_diagnostics +namespace husarion_ugv_diagnostics { SystemMonitorNode::SystemMonitorNode( @@ -101,7 +101,7 @@ float SystemMonitorNode::GetCPUMeanUsage(const std::vector & usages) cons }); auto sum = std::accumulate(usages.begin(), usages.end(), 0.0); - auto mean_usage = panther_utils::common_utilities::SetPrecision(sum / usages.size(), 2); + auto mean_usage = husarion_ugv_utils::common_utilities::SetPrecision(sum / usages.size(), 2); return mean_usage; } @@ -112,7 +112,7 @@ float SystemMonitorNode::GetCPUTemperature() const try { const auto temperature_str = filesystem_->ReadFile(kTemperatureInfoFilename); - temperature = panther_utils::common_utilities::SetPrecision( + temperature = husarion_ugv_utils::common_utilities::SetPrecision( std::stof(temperature_str) / 1000.0, 2); } catch (const std::exception & e) { RCLCPP_ERROR_STREAM( @@ -127,7 +127,8 @@ float SystemMonitorNode::GetRAMUsage() const int total = 0, free = 0, available = 0; uprofile::getSystemMemory(total, available, free); - const auto ram_usage = panther_utils::common_utilities::CountPercentage(total - available, total); + const auto ram_usage = husarion_ugv_utils::common_utilities::CountPercentage( + total - available, total); return ram_usage; } @@ -138,7 +139,8 @@ float SystemMonitorNode::GetDiskUsage() const try { const auto capacity = filesystem_->GetSpaceCapacity(kRootDirectory); const auto available = filesystem_->GetSpaceAvailable(kRootDirectory); - disk_usage = panther_utils::common_utilities::CountPercentage(capacity - available, capacity); + disk_usage = husarion_ugv_utils::common_utilities::CountPercentage( + capacity - available, capacity); } catch (const std::exception & e) { RCLCPP_ERROR_STREAM( this->get_logger(), "An exception occurred while reading disk usage: " << e.what()); @@ -196,4 +198,4 @@ void SystemMonitorNode::DiagnoseSystem(diagnostic_updater::DiagnosticStatusWrapp status.summary(error_level, message); } -} // namespace panther_diagnostics +} // namespace husarion_ugv_diagnostics diff --git a/panther_diagnostics/test/integration/system_monitor_node.test.py b/husarion_ugv_diagnostics/test/integration/system_monitor_node.test.py similarity index 97% rename from panther_diagnostics/test/integration/system_monitor_node.test.py rename to husarion_ugv_diagnostics/test/integration/system_monitor_node.test.py index dc895713..53b34bd4 100644 --- a/panther_diagnostics/test/integration/system_monitor_node.test.py +++ b/husarion_ugv_diagnostics/test/integration/system_monitor_node.test.py @@ -30,7 +30,7 @@ def generate_test_description(): system_monitor_node = Node( - package="panther_diagnostics", + package="husarion_ugv_diagnostics", executable="system_monitor_node", ) diff --git a/panther_diagnostics/test/unit/test_filesystem.cpp b/husarion_ugv_diagnostics/test/unit/test_filesystem.cpp similarity index 91% rename from panther_diagnostics/test/unit/test_filesystem.cpp rename to husarion_ugv_diagnostics/test/unit/test_filesystem.cpp index 3e9c8755..24f7a654 100644 --- a/panther_diagnostics/test/unit/test_filesystem.cpp +++ b/husarion_ugv_diagnostics/test/unit/test_filesystem.cpp @@ -18,7 +18,7 @@ #include #include -#include "panther_diagnostics/filesystem.hpp" +#include "husarion_ugv_diagnostics/filesystem.hpp" class TestFilesystem : public testing::Test { @@ -29,12 +29,13 @@ class TestFilesystem : public testing::Test void RemoveTestFile(const std::string & file_path); protected: - std::shared_ptr filesystem_; + std::shared_ptr filesystem_; static constexpr char kDummyString[] = "Hello World!"; }; -TestFilesystem::TestFilesystem() : filesystem_(std::make_shared()) +TestFilesystem::TestFilesystem() +: filesystem_(std::make_shared()) { } diff --git a/panther_diagnostics/test/unit/test_system_monitor_node.cpp b/husarion_ugv_diagnostics/test/unit/test_system_monitor_node.cpp similarity index 83% rename from panther_diagnostics/test/unit/test_system_monitor_node.cpp rename to husarion_ugv_diagnostics/test/unit/test_system_monitor_node.cpp index 8c93ff24..dd6ad053 100644 --- a/panther_diagnostics/test/unit/test_system_monitor_node.cpp +++ b/husarion_ugv_diagnostics/test/unit/test_system_monitor_node.cpp @@ -20,10 +20,10 @@ #include #include -#include "panther_diagnostics/filesystem.hpp" -#include "panther_diagnostics/system_monitor_node.hpp" +#include "husarion_ugv_diagnostics/filesystem.hpp" +#include "husarion_ugv_diagnostics/system_monitor_node.hpp" -class MockFilesystem : public panther_diagnostics::FilesystemInterface +class MockFilesystem : public husarion_ugv_diagnostics::FilesystemInterface { public: MOCK_METHOD( @@ -35,38 +35,38 @@ class MockFilesystem : public panther_diagnostics::FilesystemInterface MOCK_METHOD(std::string, ReadFile, (const std::string & file_path), (const, override)); }; -class SystemMonitorNodeWrapper : public panther_diagnostics::SystemMonitorNode +class SystemMonitorNodeWrapper : public husarion_ugv_diagnostics::SystemMonitorNode { public: SystemMonitorNodeWrapper(std::shared_ptr filesystem) - : panther_diagnostics::SystemMonitorNode("test_system_statics", filesystem) + : husarion_ugv_diagnostics::SystemMonitorNode("test_system_statics", filesystem) { } std::vector GetCoresUsages() const { - return panther_diagnostics::SystemMonitorNode::GetCoresUsages(); + return husarion_ugv_diagnostics::SystemMonitorNode::GetCoresUsages(); } float GetCPUMeanUsage(const std::vector & usages) const { - return panther_diagnostics::SystemMonitorNode::GetCPUMeanUsage(usages); + return husarion_ugv_diagnostics::SystemMonitorNode::GetCPUMeanUsage(usages); } float GetCPUTemperature() const { - return panther_diagnostics::SystemMonitorNode::GetCPUTemperature(); + return husarion_ugv_diagnostics::SystemMonitorNode::GetCPUTemperature(); } - float GetRAMUsage() const { return panther_diagnostics::SystemMonitorNode::GetRAMUsage(); } + float GetRAMUsage() const { return husarion_ugv_diagnostics::SystemMonitorNode::GetRAMUsage(); } - float GetDiskUsage() const { return panther_diagnostics::SystemMonitorNode::GetDiskUsage(); } + float GetDiskUsage() const { return husarion_ugv_diagnostics::SystemMonitorNode::GetDiskUsage(); } panther_msgs::msg::SystemStatus SystemStatusToMessage( - const panther_diagnostics::SystemStatus & status) + const husarion_ugv_diagnostics::SystemStatus & status) { - return panther_diagnostics::SystemMonitorNode::SystemStatusToMessage(status); + return husarion_ugv_diagnostics::SystemMonitorNode::SystemStatusToMessage(status); } }; @@ -160,7 +160,7 @@ TEST_F(TestSystemMonitorNode, GetDiskUsageInvalidFilesystem) TEST_F(TestSystemMonitorNode, SystemStatusToMessage) { - panther_diagnostics::SystemStatus test_status; + husarion_ugv_diagnostics::SystemStatus test_status; test_status.core_usages = {50.0, 50.0, 50.0}; test_status.cpu_mean_usage = 50.0; test_status.cpu_temperature = 36.6; diff --git a/panther_gazebo/CHANGELOG.rst b/husarion_ugv_gazebo/CHANGELOG.rst similarity index 100% rename from panther_gazebo/CHANGELOG.rst rename to husarion_ugv_gazebo/CHANGELOG.rst diff --git a/panther_gazebo/CMakeLists.txt b/husarion_ugv_gazebo/CMakeLists.txt similarity index 79% rename from panther_gazebo/CMakeLists.txt rename to husarion_ugv_gazebo/CMakeLists.txt index cae0aaa3..962f6db5 100644 --- a/panther_gazebo/CMakeLists.txt +++ b/husarion_ugv_gazebo/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10.2) -project(panther_gazebo) +project(husarion_ugv_gazebo) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) @@ -28,21 +28,21 @@ find_package(Qt5 REQUIRED COMPONENTS Core Quick QuickControls2) include_directories(include ${Qt5Core_INCLUDE_DIRS} ${Qt5Qml_INCLUDE_DIRS} ${Qt5Quick_INCLUDE_DIRS} ${Qt5QuickControls2_INCLUDE_DIRS}) -add_library(panther_simulation_plugins SHARED src/gz_panther_system.cpp) +add_library(estop_system SHARED src/estop_system.cpp) ament_target_dependencies( - panther_simulation_plugins + estop_system hardware_interface ign_ros2_control rclcpp rclcpp_lifecycle std_msgs std_srvs) -target_link_libraries(panther_simulation_plugins ignition-gazebo6) +target_link_libraries(estop_system ignition-gazebo6) set(CMAKE_AUTOMOC ON) qt5_add_resources(resources_rcc src/gui/EStop.qrc) -add_library(EStop SHARED include/panther_gazebo/gui/e_stop.hpp +add_library(EStop SHARED include/husarion_ugv_gazebo/gui/e_stop.hpp src/gui/e_stop.cpp ${resources_rcc}) ament_target_dependencies(EStop rclcpp std_srvs) target_link_libraries( @@ -60,7 +60,7 @@ target_link_libraries(LEDStrip ignition-gazebo6 ignition-msgs8 ignition-plugin1 ignition-transport11) install( - TARGETS panther_simulation_plugins + TARGETS estop_system RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) @@ -86,10 +86,8 @@ endif() ament_export_include_directories(include) -pluginlib_export_plugin_description_file(ign_ros2_control - panther_simulation_plugins.xml) +pluginlib_export_plugin_description_file(ign_ros2_control plugins.xml) -ament_environment_hooks( - "${CMAKE_CURRENT_SOURCE_DIR}/hooks/${PROJECT_NAME}.sh.in") +ament_environment_hooks("${CMAKE_CURRENT_SOURCE_DIR}/hooks/setup_envs.sh.in") ament_package() diff --git a/panther_gazebo/CONFIGURATION.md b/husarion_ugv_gazebo/CONFIGURATION.md similarity index 71% rename from panther_gazebo/CONFIGURATION.md rename to husarion_ugv_gazebo/CONFIGURATION.md index c41cc924..3ad174b3 100644 --- a/panther_gazebo/CONFIGURATION.md +++ b/husarion_ugv_gazebo/CONFIGURATION.md @@ -1,8 +1,8 @@ -# panther_gazebo +# husarion_ugv_gazebo ## Use of GPS in Simulation -The NavSat system is utilized to publish the Panther robot's position within the Gazebo world. It manages navigation satellite sensors, such as GPS, which report position and velocity in spherical coordinates (latitude/longitude) through Ignition Transport. +The NavSat system is utilized to publish the robot's position within the Gazebo world. It manages navigation satellite sensors, such as GPS, which report position and velocity in spherical coordinates (latitude/longitude) through Ignition Transport. The NavSat sensors requires the spherical coordinates of the world origin to be configured. This configuration can be accomplished, for instance, by employing the `