diff --git a/.gitignore b/.gitignore
index f42d579a3..ac9f2a85e 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/README.md b/README.md
index da2a5affc..f141f4b5b 100644
--- a/README.md
+++ b/README.md
@@ -84,6 +84,7 @@ Launch arguments are largely common to both simulation and physical robot. Howev
| --- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 🖥️ | `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`](./panther_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 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/) |
@@ -95,7 +96,6 @@ Launch arguments are largely common to both simulation and physical robot. Howev
| 🖥️ | `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`) |
@@ -103,10 +103,10 @@ Launch arguments are largely common to both simulation and physical robot. Howev
| 🤖🖥️ | `publish_robot_state` | Whether to publish the default Panther robot description.
***bool:*** `True` |
| 🖥️ | `robot_model` | Specify robot model type.
***string:*** `env(ROBOT_MODEL)` if not specified `panther` (choices: `lynx`, `panther`) |
| 🤖🖥️ | `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) |
+| 🤖🖥️ | `shutdown_hosts_config_path` | Path to file with list of hosts to request shutdown.
***string:*** [`shutdown_hosts.yaml`](./panther_manager/config/shutdown_hosts.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:*** `''` |
+| 🤖🖥️ | `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` |
diff --git a/panther_gazebo/CONFIGURATION.md b/panther_gazebo/CONFIGURATION.md
index c41cc924c..d83baf523 100644
--- a/panther_gazebo/CONFIGURATION.md
+++ b/panther_gazebo/CONFIGURATION.md
@@ -33,7 +33,7 @@ To obtain GPS data in Ignition, follow these steps:
## Linear Battery Plugin
-It is possible to simulate the battery operation of the Panther robot. By default, this feature is disabled, but you can enable it by setting the `simulate_discharging` parameter to `true` in the `battery_plugin_config.yaml` file or in the file pointed to by the `battery_config_path` parameter. Below, you will find the plugin parameters that enable battery simulation.
+It is possible to simulate the battery operation of the Panther robot. By default, this feature is disabled, but you can enable it by setting the `simulate_discharging` parameter to `true` in the `battery_plugin.yaml` file or in the file pointed to by the `battery_config_path` parameter. Below, you will find the plugin parameters that enable battery simulation.
- `simulate_discharging` [*bool*, default: **false**]: Enables battery simulation. If set to `true`, the battery will discharge **at a constant rate** (regardless of joint torque), and if it depletes completely, the robot will stop moving. When set to `false`, the battery will not discharge, but the battery status information will still be published on the `battery/battery_status` topic.
- `initial_charge_percentage` [*float*, default: **70.0**]: Sets the initial charge percentage of the battery.
diff --git a/panther_gazebo/README.md b/panther_gazebo/README.md
index a4d3bb85a..7a8189153 100644
--- a/panther_gazebo/README.md
+++ b/panther_gazebo/README.md
@@ -11,7 +11,7 @@ The package contains a launch file and source files used to run the robot simula
## Configuration Files
-- [`battery_plugin_config.yaml`](./config/battery_plugin_config.yaml): Simulated LinearBatteryPlugin configuration.
+- [`battery_plugin.yaml`](./config/battery_plugin.yaml): Simulated LinearBatteryPlugin configuration.
- [`gz_bridge.yaml`](./config/gz_bridge.yaml): Specify data to exchange between ROS and Gazebo simulation.
- [`teleop_with_estop.config`](./config/teleop_with_estop.config): Gazebo layout configuration file, which adds E-Stop and Teleop widgets.
diff --git a/panther_gazebo/config/battery_plugin_config.yaml b/panther_gazebo/config/battery_plugin.yaml
similarity index 100%
rename from panther_gazebo/config/battery_plugin_config.yaml
rename to panther_gazebo/config/battery_plugin.yaml
diff --git a/panther_gazebo/launch/simulate_robot.launch.py b/panther_gazebo/launch/simulate_robot.launch.py
index cf2829481..2bd4f822b 100644
--- a/panther_gazebo/launch/simulate_robot.launch.py
+++ b/panther_gazebo/launch/simulate_robot.launch.py
@@ -51,7 +51,7 @@ def generate_launch_description():
"This configuration is intended for use in simulations only."
),
default_value=PathJoinSubstitution(
- [FindPackageShare("panther_gazebo"), "config", "battery_plugin_config.yaml"]
+ [FindPackageShare("panther_gazebo"), "config", "battery_plugin.yaml"]
),
)
diff --git a/panther_lights/CMakeLists.txt b/panther_lights/CMakeLists.txt
index 070bd8c17..482023e35 100644
--- a/panther_lights/CMakeLists.txt
+++ b/panther_lights/CMakeLists.txt
@@ -85,7 +85,8 @@ install(
install(TARGETS panther_animation_plugins LIBRARY DESTINATION lib)
-install(DIRECTORY animations config launch DESTINATION share/${PROJECT_NAME})
+install(DIRECTORY animations config launch test
+ DESTINATION share/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_cmake_gtest REQUIRED)
diff --git a/panther_lights/CONFIGURATION.md b/panther_lights/CONFIGURATION.md
index 75f1d4345..df53c7dcd 100644
--- a/panther_lights/CONFIGURATION.md
+++ b/panther_lights/CONFIGURATION.md
@@ -2,7 +2,7 @@
## LED Animations
-Basic led configuration is loaded from [`led_config.yaml`](config/led_config.yaml) file. It includes definition of robot panels, virtual segments and default animations. Default animations can be found in the table below:
+Basic led configuration is loaded from [`{robot_model}_animations.yaml`](config) file. It includes definition of robot panels, virtual segments and default animations. Default animations can be found in the table below:
| ID | NAME | PRIORITY | ANIMATION |
| :---: | ----------------- | :------: | -------------------------------------------------- |
@@ -121,7 +121,7 @@ user_animations:
- type: panther_lights::ImageAnimation
segments: all
animation:
- image: $(find my_custom_animation_package)/animations/custom_image.png
+ image: $(find custom_pkg)/animations/custom_image.png
duration: 3
repeat: 1
@@ -133,22 +133,21 @@ user_animations:
- type: panther_lights::ImageAnimation
segments: front
animation:
- image: $(find panther_lights)/animations/triangle01_blue.png
+ image: $(find custom_pkg)/animations/front_custom_image.png
duration: 2
repeat: 2
- type: panther_lights::ImageAnimation
segments: rear
animation:
- image: $(find panther_lights)/animations/triangle01_red.png
+ image: $(find custom_pkg)/animations/rear_custom_image.png
duration: 3
repeat: 1
```
-> [!NOTE]
-> ID numbers from 0 to 19 are reserved for system animations.
-
-> [!NOTE]
-> Priority **1** is reserved for crucial system animations. Users can only define animations with priority **2** and **3**.
+> [!IMPORTANT]
+>
+> - ID numbers from 0 to 19 are reserved for system animations.
+> - Priority **1** is reserved for crucial system animations. Users can only define animations with priority **2** and **3**.
Remember to modify launch command to use user animations:
diff --git a/panther_lights/README.md b/panther_lights/README.md
index 8c1a7331f..548b04033 100644
--- a/panther_lights/README.md
+++ b/panther_lights/README.md
@@ -10,7 +10,8 @@ This package contains:
## Configuration Files
-- [`led_config.yaml`](./config/led_config.yaml): Defines and describes the appearance and parameters of the animations.
+- [`{robot_model}_animations.yaml`](./config): Defines and describes the appearance and parameters of the animations for specific robot.
+- [`{robot_model}_driver.yaml`](./config): Defines and describes specific hardware configuration for specific robot.
## ROS Nodes
@@ -29,9 +30,9 @@ This node is of type rclcpp_components is responsible for processing animations
#### Parameters
+- `~animations_config_path` [*string*, default: **$(find panther_lights)/panther_lights/config/{robot_model}_animations.yaml**]: Path to a YAML file with a description of led configuration. This file includes definition of robot panels, virtual segments and default animations.
- `~controller_frequency` [*float*, default: **50.0**]: Frequency [Hz] at which the lights controller node will process animations.
-- `~led_config_file` [*string*, default: **$(find panther_lights)/panther_lights/config/led_config.yaml**]: Path to a YAML file with a description of led configuration. This file includes definition of robot panels, virtual segments and default animations.
-- `~user_led_animations_file` [*string*, default: **None**]: Path to a YAML file with a description of the user defined animations.
+- `~user_led_animations_path` [*string*, default: **None**]: Path to a YAML file with a description of the user defined animations.
### LightsDriverNode
diff --git a/panther_lights/config/lynx_led_config.yaml b/panther_lights/config/lynx_animations.yaml
similarity index 99%
rename from panther_lights/config/lynx_led_config.yaml
rename to panther_lights/config/lynx_animations.yaml
index 0d6b36b67..44f9e2d11 100644
--- a/panther_lights/config/lynx_led_config.yaml
+++ b/panther_lights/config/lynx_animations.yaml
@@ -18,7 +18,6 @@ segments:
channel: 2
led_range: 21-11
-
segments_map:
all: [fl, fr, rl, rr]
front: [fl, fr]
diff --git a/panther_lights/config/lynx_driver.yaml b/panther_lights/config/lynx_driver.yaml
new file mode 100644
index 000000000..1dc9dca72
--- /dev/null
+++ b/panther_lights/config/lynx_driver.yaml
@@ -0,0 +1,5 @@
+/**:
+ lights_driver:
+ ros__parameters:
+ channel_1_num_led: 22
+ channel_2_num_led: 22
diff --git a/panther_lights/config/panther_led_config.yaml b/panther_lights/config/panther_animations.yaml
similarity index 100%
rename from panther_lights/config/panther_led_config.yaml
rename to panther_lights/config/panther_animations.yaml
diff --git a/panther_lights/config/panther_driver.yaml b/panther_lights/config/panther_driver.yaml
new file mode 100644
index 000000000..404dfbabf
--- /dev/null
+++ b/panther_lights/config/panther_driver.yaml
@@ -0,0 +1,5 @@
+/**:
+ lights_driver:
+ ros__parameters:
+ channel_1_num_led: 46
+ channel_2_num_led: 46
diff --git a/panther_lights/include/panther_lights/lights_controller_node.hpp b/panther_lights/include/panther_lights/lights_controller_node.hpp
index ef051bd3a..eb98f16f9 100644
--- a/panther_lights/include/panther_lights/lights_controller_node.hpp
+++ b/panther_lights/include/panther_lights/lights_controller_node.hpp
@@ -90,9 +90,9 @@ class LightsControllerNode : public rclcpp::Node
/**
* @brief Adds animations to an unordered map with animations
*
- * @param user_led_animations_file path to YAML file with user animations description
+ * @param user_led_animations_path path to YAML file with user animations description
*/
- void LoadUserAnimations(const std::string & user_led_animations_file);
+ void LoadUserAnimations(const std::string & user_led_animations_path);
/**
* @brief Adds animation to an unordered map with animations
diff --git a/panther_lights/include/panther_lights/lights_driver_node.hpp b/panther_lights/include/panther_lights/lights_driver_node.hpp
index 094dc091a..f1a4b5b5c 100644
--- a/panther_lights/include/panther_lights/lights_driver_node.hpp
+++ b/panther_lights/include/panther_lights/lights_driver_node.hpp
@@ -83,7 +83,8 @@ class LightsDriverNode : public rclcpp::Node
*/
void PanelThrottleWarnLog(const std::string panel_name, const std::string message);
- int num_led_;
+ int channel_1_num_led_;
+ int channel_2_num_led_;
double frame_timeout_;
bool led_control_granted_;
bool led_control_pending_;
diff --git a/panther_lights/launch/lights.launch.py b/panther_lights/launch/lights.launch.py
index 2f741faa8..9a97853f1 100644
--- a/panther_lights/launch/lights.launch.py
+++ b/panther_lights/launch/lights.launch.py
@@ -33,13 +33,14 @@
def generate_launch_description():
robot_model = LaunchConfiguration("robot_model")
- robot_led_config = PythonExpression(["'", robot_model, "_config.yaml'"])
- led_config_file = LaunchConfiguration("led_config_file")
- declare_led_config_file_arg = DeclareLaunchArgument(
- "led_config_file",
- default_value=PathJoinSubstitution(
- [FindPackageShare("panther_lights"), "config", robot_led_config]
- ),
+ lights_pkg = FindPackageShare("panther_lights")
+ animations_file = PythonExpression(["'", robot_model, "_animation.yaml'"])
+ default_animations_path = PathJoinSubstitution([lights_pkg, "config", animations_file])
+
+ animations_config_path = LaunchConfiguration("animations_config_path")
+ declare_animations_config_path_arg = DeclareLaunchArgument(
+ "animations_config_path",
+ default_value=default_animations_path,
description="Path to a YAML file with a description of led configuration.",
)
@@ -66,13 +67,15 @@ def generate_launch_description():
description="Whether simulation is used",
)
- user_led_animations_file = LaunchConfiguration("user_led_animations_file")
- declare_user_led_animations_file_arg = DeclareLaunchArgument(
- "user_led_animations_file",
+ user_led_animations_path = LaunchConfiguration("user_led_animations_path")
+ declare_user_led_animations_path_arg = DeclareLaunchArgument(
+ "user_led_animations_path",
default_value="",
description="Path to a YAML file with a description of the user defined animations.",
)
+ driver_file = PythonExpression(["'", robot_model, "_driver.yaml'"])
+ driver_path = PathJoinSubstitution([lights_pkg, "config", driver_file])
lights_container = ComposableNodeContainer(
package="rclcpp_components",
name="lights_container",
@@ -85,6 +88,7 @@ def generate_launch_description():
name="lights_driver",
namespace=namespace,
remappings=[("/diagnostics", "diagnostics")],
+ parameters=[driver_path],
extra_arguments=[
{"use_intra_process_comms": True},
],
@@ -96,8 +100,8 @@ def generate_launch_description():
name="lights_controller",
namespace=namespace,
parameters=[
- {"led_config_file": led_config_file},
- {"user_led_animations_file": user_led_animations_file},
+ {"animations_config_path": animations_config_path},
+ {"user_led_animations_path": user_led_animations_path},
],
extra_arguments=[
{"use_intra_process_comms": True},
@@ -109,11 +113,11 @@ def generate_launch_description():
)
actions = [
- declare_robot_model_arg, # robot_model is used by led_config_file
- declare_led_config_file_arg,
+ declare_robot_model_arg, # robot_model is used by animations_config_path
+ declare_animations_config_path_arg,
declare_namespace_arg,
declare_use_sim_arg,
- declare_user_led_animations_file_arg,
+ declare_user_led_animations_path_arg,
lights_container,
]
diff --git a/panther_lights/src/lights_controller_node.cpp b/panther_lights/src/lights_controller_node.cpp
index fb2d461f5..d77443ef7 100644
--- a/panther_lights/src/lights_controller_node.cpp
+++ b/panther_lights/src/lights_controller_node.cpp
@@ -48,23 +48,23 @@ LightsControllerNode::LightsControllerNode(const rclcpp::NodeOptions & options)
using namespace std::placeholders;
- this->declare_parameter("led_config_file");
- this->declare_parameter("user_led_animations_file", "");
+ this->declare_parameter("animations_config_path");
+ this->declare_parameter("user_led_animations_path", "");
this->declare_parameter("controller_freq", 50.0);
- const auto led_config_file = this->get_parameter("led_config_file").as_string();
- const auto user_led_animations_file = this->get_parameter("user_led_animations_file").as_string();
+ const auto animations_config_path = this->get_parameter("animations_config_path").as_string();
+ const auto user_led_animations_path = this->get_parameter("user_led_animations_path").as_string();
const float controller_freq = this->get_parameter("controller_freq").as_double();
- YAML::Node led_config_desc = YAML::LoadFile(led_config_file);
+ YAML::Node led_config_desc = YAML::LoadFile(animations_config_path);
InitializeLEDPanels(led_config_desc["panels"]);
InitializeLEDSegments(led_config_desc["segments"], controller_freq);
InitializeLEDSegmentsMap(led_config_desc["segments_map"]);
LoadDefaultAnimations(led_config_desc["led_animations"]);
- if (user_led_animations_file != "") {
- LoadUserAnimations(user_led_animations_file);
+ if (user_led_animations_path != "") {
+ LoadUserAnimations(user_led_animations_path);
}
segment_converter_ = std::make_shared();
@@ -159,12 +159,12 @@ void LightsControllerNode::LoadDefaultAnimations(const YAML::Node & animations_d
RCLCPP_INFO(this->get_logger(), "Loaded default animations.");
}
-void LightsControllerNode::LoadUserAnimations(const std::string & user_led_animations_file)
+void LightsControllerNode::LoadUserAnimations(const std::string & user_led_animations_path)
{
RCLCPP_DEBUG(this->get_logger(), "Loading user's animations.");
try {
- YAML::Node user_led_animations = YAML::LoadFile(user_led_animations_file);
+ YAML::Node user_led_animations = YAML::LoadFile(user_led_animations_path);
auto user_animations = panther_utils::GetYAMLKeyValue>(
user_led_animations, "user_animations");
diff --git a/panther_lights/src/lights_driver_node.cpp b/panther_lights/src/lights_driver_node.cpp
index e014695ae..7535955c4 100644
--- a/panther_lights/src/lights_driver_node.cpp
+++ b/panther_lights/src/lights_driver_node.cpp
@@ -54,10 +54,12 @@ LightsDriverNode::LightsDriverNode(const rclcpp::NodeOptions & options)
this->declare_parameter("global_brightness", 1.0);
this->declare_parameter("frame_timeout", 0.1);
- this->declare_parameter("num_led", 46);
+ this->declare_parameter("channel_1_num_led", 46);
+ this->declare_parameter("channel_2_num_led", 46);
frame_timeout_ = this->get_parameter("frame_timeout").as_double();
- num_led_ = this->get_parameter("num_led").as_int();
+ channel_1_num_led_ = this->get_parameter("channel_1_num_led").as_int();
+ channel_2_num_led_ = this->get_parameter("channel_2_num_led").as_int();
const float global_brightness = this->get_parameter("global_brightness").as_double();
channel_1_->SetGlobalBrightness(global_brightness);
@@ -133,8 +135,8 @@ void LightsDriverNode::InitializationTimerCB()
void LightsDriverNode::ClearLEDs()
{
- channel_1_->SetPanel(std::vector(num_led_ * 4, 0));
- channel_2_->SetPanel(std::vector(num_led_ * 4, 0));
+ channel_1_->SetPanel(std::vector(channel_1_num_led_ * 4, 0));
+ channel_2_->SetPanel(std::vector(channel_2_num_led_ * 4, 0));
}
void LightsDriverNode::ToggleLEDControl(const bool enable)
@@ -211,7 +213,9 @@ void LightsDriverNode::FrameCB(
message = "Incorrect image encoding ('" + msg->encoding + "')";
} else if (msg->height != 1) {
message = "Incorrect image height " + std::to_string(msg->height);
- } else if (msg->width != (std::uint32_t)num_led_) {
+ } else if (
+ msg->width !=
+ (std::uint32_t)(panel_name == "channel_1" ? channel_1_num_led_ : channel_2_num_led_)) {
message = "Incorrect image width " + std::to_string(msg->width);
}
diff --git a/panther_lights/test/files/animation.png b/panther_lights/test/files/animation.png
new file mode 100644
index 000000000..5886cfe10
Binary files /dev/null and b/panther_lights/test/files/animation.png differ
diff --git a/panther_lights/test/integration/panther_lights.test.py b/panther_lights/test/integration/panther_lights.test.py
index fafd6bf19..25fa0e95c 100644
--- a/panther_lights/test/integration/panther_lights.test.py
+++ b/panther_lights/test/integration/panther_lights.test.py
@@ -36,14 +36,15 @@
def generate_test_description():
- led_config_file = (
- PathJoinSubstitution([FindPackageShare("panther_lights"), "config", "led_config.yaml"]),
+ # TODO: Fix the path for specific robot model
+ animations_config_path = (
+ PathJoinSubstitution([FindPackageShare("panther_lights"), "config", "animations.yaml"]),
)
lights_controller_node = Node(
package="panther_lights",
executable="lights_controller_node",
- parameters=[{"led_config_file": led_config_file}],
+ parameters=[{"animations_config_path": animations_config_path}],
)
lights_driver_node = Node(
diff --git a/panther_lights/test/unit/animation/test_image_animation.cpp b/panther_lights/test/unit/animation/test_image_animation.cpp
index 9437bae1b..2409a30c3 100644
--- a/panther_lights/test/unit/animation/test_image_animation.cpp
+++ b/panther_lights/test/unit/animation/test_image_animation.cpp
@@ -94,21 +94,21 @@ TEST_F(TestImageAnimation, ParseImagePath)
EXPECT_EQ(this->test_image_path, animation_->ParseImagePath(this->test_image_path));
// test ROS package path
- image_path = "$(find invalid_ros_package)/animations/strip01_red.png";
+ image_path = "$(find invalid_ros_package)/test/files/animation.png";
EXPECT_THROW(animation_->ParseImagePath(image_path), std::runtime_error);
// invalid substitution
- image_path = "$(fin panther_lights)/animations/strip01_red.png";
+ image_path = "$(fin panther_lights)/test/files/animation.png";
EXPECT_THROW(animation_->ParseImagePath(image_path), std::runtime_error);
- image_path = "$(find panther_lights/animations/strip01_red.png";
+ image_path = "$(find panther_lights/test/files/animation.png";
EXPECT_THROW(animation_->ParseImagePath(image_path), std::runtime_error);
// following ones may not work if ROS package is not build or sourced
- image_path = "$(find panther_lights)/animations/strip01_red.png";
+ image_path = "$(find panther_lights)/test/files/animation.png";
EXPECT_NO_THROW(animation_->ParseImagePath(image_path));
// multiple spaces after find syntax
- image_path = "$(find panther_lights)/animations/strip01_red.png";
+ image_path = "$(find panther_lights)/test/files/animation.png";
EXPECT_NO_THROW(animation_->ParseImagePath(image_path));
}
diff --git a/panther_lights/test/unit/led_components/test_led_animation.cpp b/panther_lights/test/unit/led_components/test_led_animation.cpp
index 64dd9b024..51dbc58d4 100644
--- a/panther_lights/test/unit/led_components/test_led_animation.cpp
+++ b/panther_lights/test/unit/led_components/test_led_animation.cpp
@@ -54,7 +54,7 @@ TestLEDAnimation::TestLEDAnimation()
anim_desc.segments = {kTestSegmentName1, kTestSegmentName2};
anim_desc.type = "panther_lights::ImageAnimation";
anim_desc.animation =
- YAML::Load("{image: $(find panther_lights)/animations/triangle01_red.png, duration: 2.0}");
+ YAML::Load("{image: $(find panther_lights)/test/files/animation.png, duration: 2.0}");
panther_lights::LEDAnimationDescription led_anim_desc;
led_anim_desc.id = 0;
diff --git a/panther_lights/test/unit/led_components/test_led_animations_queue.cpp b/panther_lights/test/unit/led_components/test_led_animations_queue.cpp
index bdd9386de..4eb8d8c79 100644
--- a/panther_lights/test/unit/led_components/test_led_animations_queue.cpp
+++ b/panther_lights/test/unit/led_components/test_led_animations_queue.cpp
@@ -61,7 +61,7 @@ panther_lights::LEDAnimation TestLEDAnimationsQueue::CreateLEDAnimation(
anim_desc.segments = {"segment_1", "segment_2"};
anim_desc.type = "panther_lights::ImageAnimation";
anim_desc.animation =
- YAML::Load("{image: $(find panther_lights)/animations/triangle01_red.png, duration: 2.0}");
+ YAML::Load("{image: $(find panther_lights)/test/files/animation.png, duration: 2.0}");
panther_lights::LEDAnimationDescription led_anim_desc;
led_anim_desc.id = 0;
diff --git a/panther_lights/test/unit/led_components/test_led_segment.cpp b/panther_lights/test/unit/led_components/test_led_segment.cpp
index 9e20ff0dd..82fbec3e2 100644
--- a/panther_lights/test/unit/led_components/test_led_segment.cpp
+++ b/panther_lights/test/unit/led_components/test_led_segment.cpp
@@ -189,7 +189,7 @@ TEST_F(TestLEDSegment, SetAnimation)
{
// test each known animtion type
const auto image_anim_desc = YAML::Load(
- "{image: $(find panther_lights)/animations/triangle01_red.png, "
+ "{image: $(find panther_lights)/test/files/animation.png, "
"duration: 2}");
const auto charging_anim_desc = YAML::Load("{duration: 2}");
@@ -203,7 +203,7 @@ TEST_F(TestLEDSegment, SetAnimation)
TEST_F(TestLEDSegment, SetAnimationRepeating)
{
const auto anim_desc = YAML::Load(
- "{image: $(find panther_lights)/animations/triangle01_red.png, "
+ "{image: $(find panther_lights)/test/files/animation.png, "
"duration: 2}");
ASSERT_NO_THROW(led_segment_->SetAnimation("panther_lights::ImageAnimation", anim_desc, false));
@@ -224,7 +224,7 @@ TEST_F(TestLEDSegment, UpdateAnimationAnimationNotSet)
TEST_F(TestLEDSegment, UpdateAnimation)
{
const auto anim_desc = YAML::Load(
- "{image: $(find panther_lights)/animations/triangle01_red.png, "
+ "{image: $(find panther_lights)/test/files/animation.png, "
"duration: 2}");
ASSERT_NO_THROW(led_segment_->SetAnimation("panther_lights::ImageAnimation", anim_desc, false));
EXPECT_NO_THROW(led_segment_->UpdateAnimation());
@@ -240,7 +240,7 @@ int main(int argc, char ** argv)
TEST_F(TestLEDSegment, ResetDefaultAnimationWhenNewArrive)
{
const auto anim_desc = YAML::Load(
- "{image: $(find panther_lights)/animations/triangle01_red.png, "
+ "{image: $(find panther_lights)/test/files/animation.png, "
"duration: 2}");
ASSERT_NO_THROW(led_segment_->SetAnimation("panther_lights::ImageAnimation", anim_desc, true));
diff --git a/panther_lights/test/unit/led_components/test_segment_converter.cpp b/panther_lights/test/unit/led_components/test_segment_converter.cpp
index ef1a7747c..807f9440d 100644
--- a/panther_lights/test/unit/led_components/test_segment_converter.cpp
+++ b/panther_lights/test/unit/led_components/test_segment_converter.cpp
@@ -63,9 +63,7 @@ YAML::Node TestSegmentConverter::CreateSegmentDescription(
YAML::Node TestSegmentConverter::CreateImageAnimationDescription()
{
- return YAML::Load(
- "{image: $(find panther_lights)/animations/triangle01_red.png, "
- "duration: 2}");
+ return YAML::Load("{image: $(find panther_lights)/test/files/animation.png, duration: 2}");
}
TEST_F(TestSegmentConverter, ConvertInvalidChannel)
diff --git a/panther_lights/test/unit/test_lights_controller_node.cpp b/panther_lights/test/unit/test_lights_controller_node.cpp
index 7a27f3a40..99b0a0690 100644
--- a/panther_lights/test/unit/test_lights_controller_node.cpp
+++ b/panther_lights/test/unit/test_lights_controller_node.cpp
@@ -77,18 +77,18 @@ class TestLightsControllerNode : public testing::Test
static constexpr char kTestSegmentName[] = "test";
static constexpr char kTestSegmentLedRange[] = "0-9";
- std::filesystem::path led_config_file_;
+ std::filesystem::path animations_config_path_;
std::shared_ptr lights_controller_node_;
};
TestLightsControllerNode::TestLightsControllerNode()
{
- led_config_file_ = testing::TempDir() + "/led_config.yaml";
+ animations_config_path_ = testing::TempDir() + "/animations.yaml";
- CreateLEDConfig(led_config_file_);
+ CreateLEDConfig(animations_config_path_);
std::vector params;
- params.push_back(rclcpp::Parameter("led_config_file", led_config_file_));
+ params.push_back(rclcpp::Parameter("animations_config_path", animations_config_path_));
rclcpp::NodeOptions options;
options.parameter_overrides(params);
@@ -96,7 +96,10 @@ TestLightsControllerNode::TestLightsControllerNode()
lights_controller_node_ = std::make_shared(options);
}
-TestLightsControllerNode::~TestLightsControllerNode() { std::filesystem::remove(led_config_file_); }
+TestLightsControllerNode::~TestLightsControllerNode()
+{
+ std::filesystem::remove(animations_config_path_);
+}
void TestLightsControllerNode::CreateLEDConfig(const std::filesystem::path file_path)
{
@@ -113,7 +116,7 @@ void TestLightsControllerNode::CreateLEDConfig(const std::filesystem::path file_
segments_map["test"] = std::vector(1, kTestSegmentName);
YAML::Node animation;
- animation["image"] = "$(find panther_lights)/animations/triangle01_red.png";
+ animation["image"] = "$(find panther_lights)/test/files/strip01_red.png";
animation["duration"] = 2;
YAML::Node animation_desc;
@@ -133,14 +136,14 @@ void TestLightsControllerNode::CreateLEDConfig(const std::filesystem::path file_
led_animations.push_back(led_animation_0);
led_animations.push_back(led_animation_1);
- YAML::Node led_config;
- led_config["panels"] = std::vector(1, panel);
- led_config["segments"] = std::vector(1, segment);
- led_config["segments_map"] = segments_map;
- led_config["led_animations"] = led_animations;
+ YAML::Node animations_config;
+ animations_config["panels"] = std::vector(1, panel);
+ animations_config["segments"] = std::vector(1, segment);
+ animations_config["segments_map"] = segments_map;
+ animations_config["led_animations"] = led_animations;
YAML::Emitter out;
- out << led_config;
+ out << animations_config;
std::ofstream fout(file_path);
if (fout.is_open()) {
diff --git a/panther_lights/test/unit/test_lights_driver_node.cpp b/panther_lights/test/unit/test_lights_driver_node.cpp
index 9a20b0f5e..09918acfd 100644
--- a/panther_lights/test/unit/test_lights_driver_node.cpp
+++ b/panther_lights/test/unit/test_lights_driver_node.cpp
@@ -55,7 +55,8 @@ panther_lights::LightsDriverNode::LightsDriverNode(
channel_2_(channel_2),
diagnostic_updater_(this)
{
- num_led_ = 46;
+ channel_1_num_led_ = 46;
+ channel_2_num_led_ = 46;
frame_timeout_ = 0.1;
};
@@ -83,7 +84,10 @@ class DriverNodeWrapper : public panther_lights::LightsDriverNode
return LightsDriverNode::FrameCB(msg, panel, last_time, panel_name);
}
- int GetNumLed() const { return num_led_; }
+ int GetNumLed(const std::string & panel_name) const
+ {
+ return panel_name == "channel_1" ? channel_1_num_led_ : channel_2_num_led_;
+ }
double GetTimeout() const { return frame_timeout_; }
bool GetLedControlGranted() const { return led_control_granted_; }
bool GetLedControlPending() const { return led_control_pending_; }
@@ -98,7 +102,7 @@ class TestLightsDriverNode : public testing::Test
TestLightsDriverNode();
~TestLightsDriverNode() {};
- ImageMsg::UniquePtr CreateValidImageMsg();
+ ImageMsg::UniquePtr CreateValidImageMsg(const std::string & panel_name);
std::shared_future>
CreateSetBoolSrvFuture(bool request_data, bool response_success);
@@ -115,7 +119,7 @@ TestLightsDriverNode::TestLightsDriverNode()
lights_driver_node_ = std::make_unique(channel_1_, channel_2_);
}
-ImageMsg::UniquePtr TestLightsDriverNode::CreateValidImageMsg()
+ImageMsg::UniquePtr TestLightsDriverNode::CreateValidImageMsg(const std::string & panel_name)
{
ImageMsg::UniquePtr msg(new ImageMsg);
@@ -123,7 +127,7 @@ ImageMsg::UniquePtr TestLightsDriverNode::CreateValidImageMsg()
msg->header.stamp = lights_driver_node_->now();
msg->header.frame_id = "image_frame";
msg->height = 1;
- msg->width = lights_driver_node_->GetNumLed();
+ msg->width = lights_driver_node_->GetNumLed(panel_name);
msg->encoding = sensor_msgs::image_encodings::RGBA8;
msg->is_bigendian = false;
msg->step = msg->width * 4;
@@ -158,11 +162,13 @@ TEST_F(TestLightsDriverNode, TestInitialization)
TEST_F(TestLightsDriverNode, ClearLEDs)
{
- auto num_led = lights_driver_node_->GetNumLed();
- std::vector zero_frame(num_led * 4, 0);
+ auto num_led_1 = lights_driver_node_->GetNumLed("channel_1");
+ auto num_led_2 = lights_driver_node_->GetNumLed("channel_2");
+ std::vector zero_frame_1(num_led_1 * 4, 0);
+ std::vector zero_frame_2(num_led_2 * 4, 0);
- EXPECT_CALL(*channel_1_, SetPanel(zero_frame)).Times(1);
- EXPECT_CALL(*channel_2_, SetPanel(zero_frame)).Times(1);
+ EXPECT_CALL(*channel_1_, SetPanel(zero_frame_1)).Times(1);
+ EXPECT_CALL(*channel_2_, SetPanel(zero_frame_2)).Times(1);
lights_driver_node_->ClearLEDs();
}
@@ -203,7 +209,7 @@ TEST_F(TestLightsDriverNode, ToggleLEDControlCBDisabled)
TEST_F(TestLightsDriverNode, FrameCBSuccessNoControl)
{
- auto msg = CreateValidImageMsg();
+ auto msg = CreateValidImageMsg("channel_1");
EXPECT_CALL(*channel_1_, SetPanel(testing::_)).Times(0);
@@ -212,7 +218,8 @@ TEST_F(TestLightsDriverNode, FrameCBSuccessNoControl)
TEST_F(TestLightsDriverNode, FrameCBSuccess)
{
- auto msg = CreateValidImageMsg();
+ auto msg_1 = CreateValidImageMsg("channel_1");
+ auto msg_2 = CreateValidImageMsg("channel_2");
auto future = CreateSetBoolSrvFuture(true, true);
lights_driver_node_->ToggleLEDControlCB(std::move(future));
@@ -220,13 +227,13 @@ TEST_F(TestLightsDriverNode, FrameCBSuccess)
EXPECT_CALL(*channel_1_, SetPanel(testing::_)).Times(1);
EXPECT_CALL(*channel_2_, SetPanel(testing::_)).Times(1);
- lights_driver_node_->FrameCB(msg, channel_1_, msg->header.stamp, "channel_1");
- lights_driver_node_->FrameCB(msg, channel_2_, msg->header.stamp, "channel_2");
+ lights_driver_node_->FrameCB(msg_1, channel_1_, msg_1->header.stamp, "channel_1");
+ lights_driver_node_->FrameCB(msg_2, channel_2_, msg_2->header.stamp, "channel_2");
}
TEST_F(TestLightsDriverNode, FrameCBTimeout)
{
- auto msg = CreateValidImageMsg();
+ auto msg = CreateValidImageMsg("channel_1");
auto timeout = lights_driver_node_->GetTimeout();
// Set timestamp to exceed timeout
@@ -242,7 +249,7 @@ TEST_F(TestLightsDriverNode, FrameCBTimeout)
TEST_F(TestLightsDriverNode, FrameCBPast)
{
- auto msg = CreateValidImageMsg();
+ auto msg = CreateValidImageMsg("channel_1");
// Set last_time to be younger than msg timestamp
auto future = CreateSetBoolSrvFuture(true, true);
@@ -255,7 +262,7 @@ TEST_F(TestLightsDriverNode, FrameCBPast)
TEST_F(TestLightsDriverNode, FrameCBEncoding)
{
- auto msg = CreateValidImageMsg();
+ auto msg = CreateValidImageMsg("channel_1");
// Set incorrect encoding
msg->encoding = sensor_msgs::image_encodings::RGB8;
@@ -270,7 +277,7 @@ TEST_F(TestLightsDriverNode, FrameCBEncoding)
TEST_F(TestLightsDriverNode, FrameCBHeight)
{
- auto msg = CreateValidImageMsg();
+ auto msg = CreateValidImageMsg("channel_1");
// Set incorrect height
msg->height = 2;
@@ -285,10 +292,10 @@ TEST_F(TestLightsDriverNode, FrameCBHeight)
TEST_F(TestLightsDriverNode, FrameCBWidth)
{
- auto msg = CreateValidImageMsg();
+ auto msg = CreateValidImageMsg("channel_1");
// Set incorrect width
- msg->width = lights_driver_node_->GetNumLed() + 1;
+ msg->width = lights_driver_node_->GetNumLed("channel_1") + 1;
auto future = CreateSetBoolSrvFuture(true, true);
lights_driver_node_->ToggleLEDControlCB(std::move(future));
diff --git a/panther_manager/CONFIGURATION.md b/panther_manager/CONFIGURATION.md
index 3317e43a2..6454c886a 100644
--- a/panther_manager/CONFIGURATION.md
+++ b/panther_manager/CONFIGURATION.md
@@ -5,7 +5,7 @@
For more information regarding shutdown behavior, refer to `ShutdownSingleHost` BT node in the [Actions](#actions) section. An example of a shutdown hosts YAML file can be found below.
``` yaml
-# My shutdown_hosts_config.yaml
+# My shutdown_hosts.yaml
hosts:
# Intel NUC, user computer
- ip: 10.15.20.3
diff --git a/panther_manager/README.md b/panther_manager/README.md
index f58327f03..718abece8 100644
--- a/panther_manager/README.md
+++ b/panther_manager/README.md
@@ -17,7 +17,7 @@ This package contains:
- [`shutdown.xml`](./behavior_trees/shutdown.xml): BehaviorTree for initiating shutdown procedures.
- [`lights_manager.yaml`](./config/lights_manager.yaml): Contains parameters for the `lights_manager` node.
- [`safety_manager.yaml`](./config/safety_manager.yaml): Contains parameters for the `safety_manager` node.
-- [`shutdown_hosts_config.yaml`](./config/shutdown_hosts_config.yaml): List with all hosts to request shutdown.
+- [`shutdown_hosts.yaml`](./config/shutdown_hosts.yaml): List with all hosts to request shutdown.
## ROS Nodes
diff --git a/panther_manager/config/shutdown_hosts_config.yaml b/panther_manager/config/shutdown_hosts.yaml
similarity index 100%
rename from panther_manager/config/shutdown_hosts_config.yaml
rename to panther_manager/config/shutdown_hosts.yaml
diff --git a/panther_manager/launch/manager.launch.py b/panther_manager/launch/manager.launch.py
index 510fb2834..0aaf5385b 100644
--- a/panther_manager/launch/manager.launch.py
+++ b/panther_manager/launch/manager.launch.py
@@ -62,7 +62,7 @@ def generate_launch_description():
[
FindPackageShare("panther_manager"),
"config",
- "shutdown_hosts_config.yaml",
+ "shutdown_hosts.yaml",
]
),
description="Path to file with list of hosts to request shutdown.",