From 50bdc8b246973153eb984a15cd80dad3ffcf2d72 Mon Sep 17 00:00:00 2001 From: Roozki Date: Tue, 25 Nov 2025 00:02:53 -0800 Subject: [PATCH 01/15] add Integration test node --- src/integration_test/CMakeLists.txt | 33 ++++++++++ src/integration_test/brainstorm.txt | 4 ++ src/integration_test/package.xml | 22 +++++++ src/integration_test/src/assert_node.cpp | 63 +++++++++++++++++++ .../rv_sample_package/CMakeLists.txt | 2 +- 5 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/integration_test/CMakeLists.txt create mode 100644 src/integration_test/brainstorm.txt create mode 100644 src/integration_test/package.xml create mode 100644 src/integration_test/src/assert_node.cpp diff --git a/src/integration_test/CMakeLists.txt b/src/integration_test/CMakeLists.txt new file mode 100644 index 0000000..47ff00e --- /dev/null +++ b/src/integration_test/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.10) +project(integration_test) + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../external_pkgs/Catch2 ${CMAKE_CURRENT_BINARY_DIR}/external_pkgs/Catch2) # Include Catch2 for unit tests + +include_directories(include/) + + +# find dependencies +find_package(ament_cmake REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rover_utils REQUIRED) +find_package(sensor_msgs REQUIRED) +find_package(example_interfaces REQUIRED) + + +add_executable(integration_tester src/assert_node.cpp) +ament_target_dependencies(integration_tester rclcpp sensor_msgs rover_utils example_interfaces) + +target_link_libraries(integration_tester + Catch2::Catch2) + +install( + TARGETS + integration_tester + DESTINATION lib/${PROJECT_NAME} +) + +ament_package() diff --git a/src/integration_test/brainstorm.txt b/src/integration_test/brainstorm.txt new file mode 100644 index 0000000..efbd616 --- /dev/null +++ b/src/integration_test/brainstorm.txt @@ -0,0 +1,4 @@ +How to integration tests? + +scopeout: +1. can catch2 be used? or should not bother? \ No newline at end of file diff --git a/src/integration_test/package.xml b/src/integration_test/package.xml new file mode 100644 index 0000000..f86e689 --- /dev/null +++ b/src/integration_test/package.xml @@ -0,0 +1,22 @@ + + + + integration_test + 0.0.0 + TODO: Package description + rowan + TODO: License declaration + + ament_cmake + + rclcpp + rover_utils + sensor_msgs + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/src/integration_test/src/assert_node.cpp b/src/integration_test/src/assert_node.cpp new file mode 100644 index 0000000..354b5bf --- /dev/null +++ b/src/integration_test/src/assert_node.cpp @@ -0,0 +1,63 @@ +// name? + +#include +#include +#include +#include + +// Class definition +class IntegrationTestNode : public rclcpp::Node { +public: + IntegrationTestNode(); // Constructor is defined in .cpp. + +private: + // SUBS AND PUBS + rclcpp::Publisher::SharedPtr joy_publisher; + + rclcpp::Publisher::SharedPtr checker_pub; + rclcpp::Subscription::SharedPtr checker_sub; + + // Callbacks + void test_callback(example_interfaces::msg::Int32 msg); + +}; + +// Constructor +IntegrationTestNode::IntegrationTestNode() : Node("integration_test_node") +{ // We create a class using rclcpp::Node as a base class. You can still use another base class if you need, albeit sometimes with difficulties in passing args.. + + // Quality of service example + auto qos = rclcpp::QoS(rclcpp::KeepLast(1)).transient_local(); + + joy_publisher = this->create_publisher( + "/joy", qos); + + checker_pub = this->create_publisher( + "/integration/test_int", qos); + + checker_sub = this->create_subscription( + "/integration/test_int", qos, std::bind(&IntegrationTestNode::test_callback, this, std::placeholders::_1)); + +} + +// Main function (entry point of node) +int main(int argc, char *argv[]) +{ + // Init ros2 with args. + rclcpp::init(argc, argv); + + // Instatiate your node + auto node = std::make_shared(); + // Spin it! (this is what runs pubs and subs. This is a blocking function) + rclcpp::spin(node); + // There is also rclcpp::spinSome(node) if you need more control over when the node spins / need to not block while spinning. + + // Code only reaches here if we crash or shutdown the node + rclcpp::shutdown(); + return 0; +} + +void IntegrationTestNode::test_callback(example_interfaces::msg::Int32 msg) +{ + +} \ No newline at end of file diff --git a/src/rover_samples/rv_sample_package/CMakeLists.txt b/src/rover_samples/rv_sample_package/CMakeLists.txt index b6197ef..9ee6351 100644 --- a/src/rover_samples/rv_sample_package/CMakeLists.txt +++ b/src/rover_samples/rv_sample_package/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) project(rv_sample_package) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") From 91d962b7cd4be66c5e9ef9c8efcb225408fbb4a7 Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 18:52:02 -0800 Subject: [PATCH 02/15] integration test added for arm --- src/arm_control/CMakeLists.txt | 1 + src/arm_control/include/armControlParams.h | 1 + src/arm_control/include/cbs_interface.h | 13 +- src/arm_control/src/cbs_interface.cpp | 2 +- src/integration_test/CMakeLists.txt | 26 +++- .../integration_helper_macros.h | 4 + src/integration_test/package.xml | 7 + src/integration_test/src/assert_node.cpp | 27 +++- .../src/example_multiply_by_two_node.cpp | 52 +++++++ .../src/integration_test_fixtures.cpp | 54 +++++++ .../test/test_arm_pipeline.py | 144 ++++++++++++++++++ src/integration_test/test/test_launch_test.py | 77 ++++++++++ 12 files changed, 387 insertions(+), 21 deletions(-) create mode 100644 src/integration_test/include/integration_test/integration_helper_macros.h create mode 100644 src/integration_test/src/example_multiply_by_two_node.cpp create mode 100644 src/integration_test/src/integration_test_fixtures.cpp create mode 100644 src/integration_test/test/test_arm_pipeline.py create mode 100644 src/integration_test/test/test_launch_test.py diff --git a/src/arm_control/CMakeLists.txt b/src/arm_control/CMakeLists.txt index 3522498..9218698 100644 --- a/src/arm_control/CMakeLists.txt +++ b/src/arm_control/CMakeLists.txt @@ -29,6 +29,7 @@ set(THIS_PACKAGE_INCLUDE_DEPENDS trajectory_msgs rover_msgs moteus_msgs + arm_hardware_interface ) find_package(ament_cmake REQUIRED) diff --git a/src/arm_control/include/armControlParams.h b/src/arm_control/include/armControlParams.h index 7143cf5..6e84a28 100644 --- a/src/arm_control/include/armControlParams.h +++ b/src/arm_control/include/armControlParams.h @@ -16,6 +16,7 @@ #define EE_SPEED_SCALE 1 #define PI 3.14 +//TODO get away from this style of conditional compiling. // Uncomment the one you want, comment the one you dont #define SELECT_MOTEUS_ARM // #define SELECT_OLD_ARM diff --git a/src/arm_control/include/cbs_interface.h b/src/arm_control/include/cbs_interface.h index f52b5da..4e7a320 100644 --- a/src/arm_control/include/cbs_interface.h +++ b/src/arm_control/include/cbs_interface.h @@ -4,8 +4,7 @@ #include "armControlParams.h" #include "rover_msgs/msg/generic_panel.hpp" #include "geometry_msgs/msg/twist_stamped.hpp" - - +#include class CBSArmInterface : public rclcpp::Node { @@ -14,19 +13,17 @@ class CBSArmInterface : public rclcpp::Node auto qos = rclcpp::QoS(rclcpp::KeepLast(1)).transient_local(); arm_cmd_publisher = this->create_publisher("/arm/command", qos); - arm_panel_subscriber = this->create_subscription( + arm_panel_subscriber = this->create_subscription( "/cbs/arm_panel", 10, std::bind(&CBSArmInterface::arm_panel_callback, this, std::placeholders::_1)); left_panel_subscriber = this->create_subscription( "/cbs/left_panel_a", 10, std::bind(&CBSArmInterface::left_panel_callback, this, std::placeholders::_1)); - - arm_ik_pub = this->create_publisher( - "/arm_moveit_control/delta_twist_cmds", qos); + + arm_ik_pub = this->create_publisher( + "/arm_moveit_control/delta_twist_cmds", qos); // arm_panel_timer = this->create_wall_timer( //Timer setup if we need it // std::chrono::milliseconds(10), // Timer interval // std::bind(&CBSManagerNode::armPanelPoll, this) // Callback function // ); - - } ~CBSArmInterface(){ diff --git a/src/arm_control/src/cbs_interface.cpp b/src/arm_control/src/cbs_interface.cpp index 9da7f3c..fbd6f6e 100644 --- a/src/arm_control/src/cbs_interface.cpp +++ b/src/arm_control/src/cbs_interface.cpp @@ -45,7 +45,7 @@ void CBSArmInterface::arm_panel_callback(const rover_msgs::msg::ArmPanel::Shared rover_msgs::msg::ArmCommand cmd_msg; - cmd_msg.cmd_type = 'V'; //!SHOULD BE FROM ArmSerialProtocol.h + cmd_msg.cmd_type = ABS_VEL_CMD; //!SHOULD BE FROM ArmSerialProtocol.h cmd_msg.velocities.resize(NUM_JOINTS); cmd_msg.velocities[0] = (static_cast(msg->left.x) - 50)/100 * max_joysticks_output_speed_deg[0]*2; cmd_msg.velocities[1] = (static_cast(msg->left.y) - 50)/100 * max_joysticks_output_speed_deg[1]*2 *-1; diff --git a/src/integration_test/CMakeLists.txt b/src/integration_test/CMakeLists.txt index 47ff00e..9f8b8d5 100644 --- a/src/integration_test/CMakeLists.txt +++ b/src/integration_test/CMakeLists.txt @@ -5,11 +5,12 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() -add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../external_pkgs/Catch2 ${CMAKE_CURRENT_BINARY_DIR}/external_pkgs/Catch2) # Include Catch2 for unit tests +# Catch2 did not work very well. We tried, its just difficult to integrate in a scalable way. +# leaving this stale code just commented to keep record that we tried it. +# add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../external_pkgs/Catch2 ${CMAKE_CURRENT_BINARY_DIR}/external_pkgs/Catch2) # Include Catch2 for unit tests include_directories(include/) - # find dependencies find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) @@ -17,16 +18,31 @@ find_package(rover_utils REQUIRED) find_package(sensor_msgs REQUIRED) find_package(example_interfaces REQUIRED) - add_executable(integration_tester src/assert_node.cpp) +add_executable(example_multiply_by_two_node src/example_multiply_by_two_node.cpp) ament_target_dependencies(integration_tester rclcpp sensor_msgs rover_utils example_interfaces) +ament_target_dependencies(example_multiply_by_two_node rclcpp sensor_msgs rover_utils example_interfaces) + +if(BUILD_TESTING) + # Integration tests + find_package(ament_cmake_ros REQUIRED) + find_package(launch_testing_ament_cmake REQUIRED) + function(add_ros_isolated_launch_test path) + set(RUNNER "${ament_cmake_ros_DIR}/run_test_isolated.py") + add_launch_test("${path}" RUNNER "${RUNNER}" ${ARGN}) + endfunction() + add_ros_isolated_launch_test(test/test_launch_test.py) + add_ros_isolated_launch_test(test/test_arm_pipeline.py) + # Add more tests here +endif() -target_link_libraries(integration_tester - Catch2::Catch2) +# target_link_libraries(integration_tester +# Catch2::Catch2) install( TARGETS integration_tester + example_multiply_by_two_node DESTINATION lib/${PROJECT_NAME} ) diff --git a/src/integration_test/include/integration_test/integration_helper_macros.h b/src/integration_test/include/integration_test/integration_helper_macros.h new file mode 100644 index 0000000..ad67e1e --- /dev/null +++ b/src/integration_test/include/integration_test/integration_helper_macros.h @@ -0,0 +1,4 @@ +#pragma once + + +// #define APPROX() \ No newline at end of file diff --git a/src/integration_test/package.xml b/src/integration_test/package.xml index f86e689..c36172c 100644 --- a/src/integration_test/package.xml +++ b/src/integration_test/package.xml @@ -12,6 +12,13 @@ rclcpp rover_utils sensor_msgs + + ament_cmake_ros + launch + launch_ros + launch_testing + launch_testing_ament_cmake + rclpy ament_lint_auto ament_lint_common diff --git a/src/integration_test/src/assert_node.cpp b/src/integration_test/src/assert_node.cpp index 354b5bf..1e394ff 100644 --- a/src/integration_test/src/assert_node.cpp +++ b/src/integration_test/src/assert_node.cpp @@ -1,9 +1,12 @@ -// name? - #include #include #include -#include +// #include + +// This node is a work in progress, playing around with different ways to setup integration tests. +// We are aiming for a standard, easy way to add tests, and an easy way to get test results. + +#define TEST_INT_VALUE 50 // Class definition class IntegrationTestNode : public rclcpp::Node { @@ -33,11 +36,14 @@ IntegrationTestNode::IntegrationTestNode() : Node("integration_test_node") "/joy", qos); checker_pub = this->create_publisher( - "/integration/test_int", qos); + "/integration/test_int/output", qos); checker_sub = this->create_subscription( - "/integration/test_int", qos, std::bind(&IntegrationTestNode::test_callback, this, std::placeholders::_1)); - + "/integration/test_int/input", qos, std::bind(&IntegrationTestNode::test_callback, this, std::placeholders::_1)); + + // example_interfaces::msg::Int32 test_msg; + // test_msg.data = TEST_INT_VALUE; + // checker_pub->publish(test_msg); } // Main function (entry point of node) @@ -59,5 +65,12 @@ int main(int argc, char *argv[]) void IntegrationTestNode::test_callback(example_interfaces::msg::Int32 msg) { - + example_interfaces::msg::Int32 output; + output.data = msg.data *2; + checker_pub->publish(output); + // TEST_CASE("integration test check") + // { + // REQUIRE(true); + // REQUIRE(msg.data == TEST_INT_VALUE); + // } } \ No newline at end of file diff --git a/src/integration_test/src/example_multiply_by_two_node.cpp b/src/integration_test/src/example_multiply_by_two_node.cpp new file mode 100644 index 0000000..08227b6 --- /dev/null +++ b/src/integration_test/src/example_multiply_by_two_node.cpp @@ -0,0 +1,52 @@ +#include +#include + +// This node is just an example node to show integration tests +// Its just one publisher and one subscriber, give it an integer and it just doubles it + +// Class definition +class MultiplyBy2Node : public rclcpp::Node { +public: + MultiplyBy2Node(); // Constructor is defined in .cpp. + +private: + // SUBS AND PUBS + rclcpp::Publisher::SharedPtr output_pub; + rclcpp::Subscription::SharedPtr input_sub; + + // Callbacks + void test_callback(example_interfaces::msg::Int32 msg); + +}; + +// Constructor +MultiplyBy2Node::MultiplyBy2Node() : Node("multiply_by_two_integration_test_example_node") +{ // We create a class using rclcpp::Node as a base class. You can still use another base class if you need, albeit sometimes with difficulties in passing args.. + + // Quality of service example + auto qos = rclcpp::QoS(rclcpp::KeepLast(1)).transient_local(); + + output_pub = this->create_publisher( + "/integration/test_int/output", qos); + + input_sub = this->create_subscription( + "/integration/test_int/input", qos, std::bind(&MultiplyBy2Node::test_callback, this, std::placeholders::_1)); + + RCLCPP_INFO(this->get_logger(), "Example Log message: Node has started"); +} + +int main(int argc, char *argv[]) +{ + rclcpp::init(argc, argv); + auto node = std::make_shared(); + rclcpp::spin(node); + rclcpp::shutdown(); + return 0; +} + +void MultiplyBy2Node::test_callback(example_interfaces::msg::Int32 msg) +{ + example_interfaces::msg::Int32 output; + output.data = msg.data *2; + output_pub->publish(output); +} \ No newline at end of file diff --git a/src/integration_test/src/integration_test_fixtures.cpp b/src/integration_test/src/integration_test_fixtures.cpp new file mode 100644 index 0000000..c3c2098 --- /dev/null +++ b/src/integration_test/src/integration_test_fixtures.cpp @@ -0,0 +1,54 @@ +// This class is meant to be a helper class for integration tests. +#include +#include +#include + +// Work in progress... + +// A single test +class TestRunner { +public: + TestRunner(std::string name) {}; + + void assert(bool assertion) + { + + } + + void assert(float val1, float val2, float thresh = 0.0000001) + { + + } + + +private: + std::string name; +}; + +class IntegrationTestHelper { +public: + IntegrationTestHelper() : next_test_index(0), current_test_index(0) {}; + + TestRunner& add_test(std::string name); + +private: + std::unordered_map tests; + uint32_t next_test_index; + uint32_t current_test_index; +}; + +TestRunner& IntegrationTestHelper::add_test(std::string name) +{ + current_test_index = next_test_index; + tests.emplace(current_test_index, TestRunner(name)); + next_test_index++; + return tests[current_test_index]; +} + + + + + +// Example usage: + +// auto new_test = test.add_test("My new test"); \ No newline at end of file diff --git a/src/integration_test/test/test_arm_pipeline.py b/src/integration_test/test/test_arm_pipeline.py new file mode 100644 index 0000000..087be35 --- /dev/null +++ b/src/integration_test/test/test_arm_pipeline.py @@ -0,0 +1,144 @@ +import os +import sys +import time +import unittest + +import launch +import launch_ros +import launch_testing.actions +import rclpy +from example_interfaces.msg import Int32 +from rclpy.qos import QoSProfile, QoSDurabilityPolicy, QoSReliabilityPolicy +from rover_msgs.msg import GenericPanel +from rover_msgs.msg import ArmPanel +from rover_msgs.msg import ArmCommand +from geometry_msgs.msg import TwistStamped + + + +def generate_test_description(): + return ( + launch.LaunchDescription( + [ + # Nodes under test + launch_ros.actions.Node( + package='arm_control', + namespace='', + executable='cbs_arm_interface', + name='cbs_arm_interface', + ), + # Launch tests 1.5 s later + launch.actions.TimerAction( + period=0.5, actions=[launch_testing.actions.ReadyToTest()]), + ] + ), {}, + ) + + + +# Active tests + +# Control Base Station Input -> arm command output test +# Injects inputs that would come from the CBS +# Asserts on arm command topics +CBS_INTERFACE_TEST_TIME_SECONDS = 1 +CBS_INTERFACE_TIME_NEEDED_TO_RESPOND_SECONDS = 0.05 # Node under test has a qos depth of 1 (can only process one msg per sub at a time), so rapid firing publishers will cause undef behaviour. +class CBSInterfaceTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() + + def setUp(self): + self.node = rclpy.create_node('cbs_interface_test') + + def tearDown(self): + self.node.destroy_node() + + def test_publishes_pose(self, proc_output): + """Check whether pose messages published""" + qos = QoSProfile(depth=10) # using a higher qos just to facilitate slower spin times + qos.durability = QoSDurabilityPolicy.TRANSIENT_LOCAL + qos.reliability = QoSReliabilityPolicy.RELIABLE + arm_cmd_msgs = [] # raw arm msgs + ik_twist_msgs = [] # ik messages + + ik_sub = self.node.create_subscription( + TwistStamped, '/arm_moveit_control/delta_twist_cmds', + lambda msg: ik_twist_msgs.append(msg), qos) + arm_sub = self.node.create_subscription( + ArmCommand, '/arm/command', + lambda msg: arm_cmd_msgs.append(msg), qos) + + arm_panel_pub = self.node.create_publisher(ArmPanel, '/cbs/arm_panel', qos) + left_panel_a_pub = self.node.create_publisher(GenericPanel, '/cbs/left_panel_a', qos) + try: + + # Inject an arm panel message + injection = ArmPanel() + injection.left.x = 50 + injection.left.y = 50 + injection.left.z = 50 + injection.right.x = 50 + injection.right.y = 50 + injection.right.z = 50 + injection.right.button = 0 + injection.left.button = 0 + arm_panel_pub.publish(injection) # injection 0, should be all 0s + time.sleep(CBS_INTERFACE_TIME_NEEDED_TO_RESPOND_SECONDS) # needed to let the node under test respond + injection.right.button = 1 + arm_panel_pub.publish(injection) # injection 1, end effector should move + time.sleep(CBS_INTERFACE_TIME_NEEDED_TO_RESPOND_SECONDS) + injection.right.button = 0 + injection.left.button = 1 + arm_panel_pub.publish(injection) # injection 2, end effector should move in other direction + time.sleep(CBS_INTERFACE_TIME_NEEDED_TO_RESPOND_SECONDS) + injection.left.button = 0 + injection.left.x = 80 + arm_panel_pub.publish(injection) # injection 3, axis 1 should move positive + time.sleep(CBS_INTERFACE_TIME_NEEDED_TO_RESPOND_SECONDS) + injection.left.x = 23 + arm_panel_pub.publish(injection) # injection 4, axis 1 should move negative + time.sleep(CBS_INTERFACE_TIME_NEEDED_TO_RESPOND_SECONDS) + + end_time = time.time() + CBS_INTERFACE_TEST_TIME_SECONDS + while time.time() < end_time: + # spin to get subscriber callback executed + rclpy.spin_once(self.node, timeout_sec=0.1) + # There should have been 1 message received + assert len(arm_cmd_msgs) > 0 + assert len(ik_twist_msgs) == 0 # control pipeline should not be sending any twist messages yet + for value in arm_cmd_msgs[0].velocities: + assert(value == 0) + assert(arm_cmd_msgs[0].end_effector == 0.0) + assert(arm_cmd_msgs[0].cmd_type == ord('V')) + assert(arm_cmd_msgs[1].end_effector > 0.0) + assert(arm_cmd_msgs[2].end_effector < 0.0) + assert(arm_cmd_msgs[3].velocities[0] > 0.0) + assert(arm_cmd_msgs[4].velocities[0] < 0.0) + + num_direct_commands = len(arm_cmd_msgs) + left_panel_injection = GenericPanel() + left_panel_injection.switches.append(False) # Inject IK switch setting + left_panel_injection.switches[0] = True # Inject IK switch setting + left_panel_a_pub.publish(left_panel_injection) + time.sleep(CBS_INTERFACE_TIME_NEEDED_TO_RESPOND_SECONDS) + arm_panel_pub.publish(injection) + time.sleep(CBS_INTERFACE_TIME_NEEDED_TO_RESPOND_SECONDS) + rclpy.spin_once(self.node, timeout_sec=0.1) + + assert len(arm_cmd_msgs) == num_direct_commands # No new arm cmd messages should be published + assert len(ik_twist_msgs) == 1 + assert(ik_twist_msgs[0].twist.linear.x != 0) + + + + finally: + self.node.destroy_subscription(arm_sub) + self.node.destroy_subscription(ik_sub) + self.node.destroy_publisher(arm_panel_pub) + self.node.destroy_publisher(left_panel_a_pub) + diff --git a/src/integration_test/test/test_launch_test.py b/src/integration_test/test/test_launch_test.py new file mode 100644 index 0000000..f77bf0e --- /dev/null +++ b/src/integration_test/test/test_launch_test.py @@ -0,0 +1,77 @@ +import os +import sys +import time +import unittest + +import launch +import launch_ros +import launch_testing.actions +import rclpy +from example_interfaces.msg import Int32 +from rclpy.qos import QoSProfile, QoSDurabilityPolicy + + +def generate_test_description(): + return ( + launch.LaunchDescription( + [ + # Nodes under test + launch_ros.actions.Node( + package='integration_test', + namespace='', + executable='example_multiply_by_two_node', + name='multiply_by_two_node', + ), + # Launch tests 0.5 s later + launch.actions.TimerAction( + period=0.5, actions=[launch_testing.actions.ReadyToTest()]), + ] + ), {}, + ) + +# Active tests +class TestExample(unittest.TestCase): + @classmethod + def setUpClass(cls): + rclpy.init() + + @classmethod + def tearDownClass(cls): + rclpy.shutdown() + + def setUp(self): + self.node = rclpy.create_node('test_example') + + def tearDown(self): + self.node.destroy_node() + + def test_publishes_pose(self, proc_output): + """Check whether pose messages published""" + qos = QoSProfile(depth=10) + qos.durability = QoSDurabilityPolicy.TRANSIENT_LOCAL + + msgs_rx = [] + sub = self.node.create_subscription( + Int32, '/integration/test_int/output', + lambda msg: msgs_rx.append(msg), qos) + pub = self.node.create_publisher(Int32, '/integration/test_int/input', qos) + try: + # Listen to the pose topic for 10 s + injection = Int32() + injection.data = 5 + pub.publish(injection) + end_time = time.time() + 1 + while time.time() < end_time: + # spin to get subscriber callback executed + rclpy.spin_once(self.node, timeout_sec=1) + # There should have been 1 message received + assert len(msgs_rx) > 0 + assert msgs_rx[0].data == 10 + finally: + self.node.destroy_subscription(sub) + + def test_logs_spawning(self, proc_output): + """Check whether logging properly""" + proc_output.assertWaitFor( + "Example Log message: Node has started", + timeout=5, stream='stderr') From 51199c5279a99a248d8460f6104be46619392297 Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:06:13 -0800 Subject: [PATCH 03/15] modify github workflow --- .github/workflows/install_and_build.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index 6697601..2231ee3 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -1,15 +1,17 @@ name: Run setup and colcon build for Dev on: push jobs: - setup_and_build_check: + ci: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: enviroment setupg + id: setup run: | export ROVERFLAKE_ROOT="${GITHUB_WORKSPACE}" yes | ./setup_scripts/setup_everything_common.sh - name: build + id: build run: | cd $ROVERFLAKE_ROOT echo $ROS_DISTRO From 170d0747af22529e7abb0c0092f4cbf7c1333b7a Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:09:10 -0800 Subject: [PATCH 04/15] try again --- .github/workflows/install_and_build.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index 2231ee3..2a0de21 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -36,4 +36,7 @@ jobs: message: | _you have saddened me ${{ github.actor }}_ ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} +outputs: + build_status: ${{ steps.build.outcome }} + test_status: ${{ steps.setup.outcome }} From 204a2ed10f20244efd80b6421c7adde428f73ded Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:16:36 -0800 Subject: [PATCH 05/15] trying not to rebuild --- .github/workflows/install_and_build.yaml | 14 ++++++------ .github/workflows/integration_tests.yaml | 29 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/integration_tests.yaml diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index 2a0de21..8749c4d 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -1,23 +1,26 @@ name: Run setup and colcon build for Dev on: push jobs: - ci: + setup_and_build_check: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: enviroment setupg - id: setup run: | export ROVERFLAKE_ROOT="${GITHUB_WORKSPACE}" yes | ./setup_scripts/setup_everything_common.sh - name: build - id: build run: | cd $ROVERFLAKE_ROOT echo $ROS_DISTRO source /opt/ros/humble/setup.bash echo $ROS_DISTRO - colcon build --symlink-install --packages-skip sweeppy + colcon build --symlink-install --packages-skip sweeppy + - uses: actions/upload-artifact@v3 + with: + name: rover_ws + path: install/ + - name: Notify Discord (success) if: ${{ success() }} uses: appleboy/discord-action@v1.0.0 @@ -36,7 +39,4 @@ jobs: message: | _you have saddened me ${{ github.actor }}_ ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} -outputs: - build_status: ${{ steps.build.outcome }} - test_status: ${{ steps.setup.outcome }} diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml new file mode 100644 index 0000000..f05acb8 --- /dev/null +++ b/.github/workflows/integration_tests.yaml @@ -0,0 +1,29 @@ +name: Run Integration Tests +on: push +jobs: + integration_tests: + needs: setup_and_build_check + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: # added this, might fix a bug that's taken over 3 hours to find + submodules: recursive + - uses: actions/download-artifact@v3 + with: + name: rover_ws + path: install/ + - name: integration_tests + run: | + cd ${GITHUB_WORKSPACE} + colcon test --packages-select integration_tests + - name: Notify Discord (failure) + if: ${{ failure() }} + uses: appleboy/discord-action@v1.0.0 + with: + webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} # it also accepts full URL + webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} # it also accepts full URL + message: | + _Unit tests have failed ${{ github.actor }}_ + ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + @rowan Check for integration misshaps + From dc835a13ef1a70059c342b1cbfe3d94f6788d615 Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:17:43 -0800 Subject: [PATCH 06/15] bump workflows version --- .github/workflows/install_and_build.yaml | 2 +- .github/workflows/integration_tests.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index 8749c4d..da3232a 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -16,7 +16,7 @@ jobs: source /opt/ros/humble/setup.bash echo $ROS_DISTRO colcon build --symlink-install --packages-skip sweeppy - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: name: rover_ws path: install/ diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml index f05acb8..e4fd506 100644 --- a/.github/workflows/integration_tests.yaml +++ b/.github/workflows/integration_tests.yaml @@ -8,7 +8,7 @@ jobs: - uses: actions/checkout@v4 with: # added this, might fix a bug that's taken over 3 hours to find submodules: recursive - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: rover_ws path: install/ From f291a91eade7a572be2a4499fb0695d45c7a926c Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:37:41 -0800 Subject: [PATCH 07/15] why test no run --- .github/workflows/integration_tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml index e4fd506..cb15f94 100644 --- a/.github/workflows/integration_tests.yaml +++ b/.github/workflows/integration_tests.yaml @@ -2,7 +2,7 @@ name: Run Integration Tests on: push jobs: integration_tests: - needs: setup_and_build_check + needs: build runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 From d6710ffb36feb54565460626481d16fdc972e1fc Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:40:35 -0800 Subject: [PATCH 08/15] try again --- .github/workflows/install_and_build.yaml | 28 ++++++++++++++++++++++- .github/workflows/integration_tests.yaml | 29 ------------------------ 2 files changed, 27 insertions(+), 30 deletions(-) delete mode 100644 .github/workflows/integration_tests.yaml diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index da3232a..272dfaa 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -39,4 +39,30 @@ jobs: message: | _you have saddened me ${{ github.actor }}_ ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - + integration_tests: + runs-on: ubuntu-22.04 + needs: setup_and_build_check + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: rover_ws + path: install/ + - name: run integration tests + run: | + source install/setup.bash + colcon test --packages-select integration_tests + colcon test-result --verbose + - name: Notify Discord (failure) + if: ${{ failure() }} + uses: appleboy/discord-action@v1.0.0 + with: + webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} # it also accepts full URL + webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} # it also accepts full URL + message: | + _Unit tests have failed ${{ github.actor }}_ + ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + @rowan Check for integration misshaps + + + diff --git a/.github/workflows/integration_tests.yaml b/.github/workflows/integration_tests.yaml deleted file mode 100644 index cb15f94..0000000 --- a/.github/workflows/integration_tests.yaml +++ /dev/null @@ -1,29 +0,0 @@ -name: Run Integration Tests -on: push -jobs: - integration_tests: - needs: build - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - with: # added this, might fix a bug that's taken over 3 hours to find - submodules: recursive - - uses: actions/download-artifact@v4 - with: - name: rover_ws - path: install/ - - name: integration_tests - run: | - cd ${GITHUB_WORKSPACE} - colcon test --packages-select integration_tests - - name: Notify Discord (failure) - if: ${{ failure() }} - uses: appleboy/discord-action@v1.0.0 - with: - webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} # it also accepts full URL - webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} # it also accepts full URL - message: | - _Unit tests have failed ${{ github.actor }}_ - ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - @rowan Check for integration misshaps - From c7449445304b9ba9635c76a79a6526325adb1610 Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:41:35 -0800 Subject: [PATCH 09/15] try again --- .github/workflows/install_and_build.yaml | 50 ++++++++++++------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index 272dfaa..611897d 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -39,30 +39,30 @@ jobs: message: | _you have saddened me ${{ github.actor }}_ ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - integration_tests: - runs-on: ubuntu-22.04 - needs: setup_and_build_check - steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: rover_ws - path: install/ - - name: run integration tests - run: | - source install/setup.bash - colcon test --packages-select integration_tests - colcon test-result --verbose - - name: Notify Discord (failure) - if: ${{ failure() }} - uses: appleboy/discord-action@v1.0.0 - with: - webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} # it also accepts full URL - webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} # it also accepts full URL - message: | - _Unit tests have failed ${{ github.actor }}_ - ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - @rowan Check for integration misshaps - + integration_tests: + runs-on: ubuntu-22.04 + needs: setup_and_build_check + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: rover_ws + path: install/ + - name: run integration tests + run: | + source install/setup.bash + colcon test --packages-select integration_tests + colcon test-result --verbose + - name: Notify Discord (failure) + if: ${{ failure() }} + uses: appleboy/discord-action@v1.0.0 + with: + webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} # it also accepts full URL + webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} # it also accepts full URL + message: | + _Unit tests have failed ${{ github.actor }}_ + ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + @rowan Check for integration misshaps + From 90329aa9272d3166f3e9fe3ad4d51517afb18105 Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:42:41 -0800 Subject: [PATCH 10/15] why is this so hard to debug --- .github/workflows/install_and_build.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index 611897d..b4d0df6 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -62,7 +62,4 @@ jobs: message: | _Unit tests have failed ${{ github.actor }}_ ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - @rowan Check for integration misshaps - - - + @rowan Check for integration misshaps \ No newline at end of file From 39f10e69b4f6d278736bde9f9f55f3345c66d2d0 Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:45:33 -0800 Subject: [PATCH 11/15] ahh --- .github/workflows/install_and_build.yaml | 40 ++++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index b4d0df6..a5f1863 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -43,23 +43,23 @@ jobs: runs-on: ubuntu-22.04 needs: setup_and_build_check steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: rover_ws - path: install/ - - name: run integration tests - run: | - source install/setup.bash - colcon test --packages-select integration_tests - colcon test-result --verbose - - name: Notify Discord (failure) - if: ${{ failure() }} - uses: appleboy/discord-action@v1.0.0 - with: - webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} # it also accepts full URL - webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} # it also accepts full URL - message: | - _Unit tests have failed ${{ github.actor }}_ - ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - @rowan Check for integration misshaps \ No newline at end of file + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v4 + with: + name: rover_ws + path: install/ + - name: run integration tests + run: | + source install/setup.bash + colcon test --packages-select integration_tests + colcon test-result --verbose + - name: Notify Discord (failure) + if: ${{ failure() }} + uses: appleboy/discord-action@v1.0.0 + with: + webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} # it also accepts full URL + webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} # it also accepts full URL + message: | + _Unit tests have failed ${{ github.actor }}_ + ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + @rowan Check for integration misshaps \ No newline at end of file From 3c287c60dc62d4b030d60c6d62af330a518e41d4 Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:48:13 -0800 Subject: [PATCH 12/15] indendation ffs --- .github/workflows/install_and_build.yaml | 118 ++++++++++++----------- 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index a5f1863..c7d5859 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -1,65 +1,75 @@ name: Run setup and colcon build for Dev on: push + jobs: + setup_and_build_check: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 - - name: enviroment setupg - run: | - export ROVERFLAKE_ROOT="${GITHUB_WORKSPACE}" - yes | ./setup_scripts/setup_everything_common.sh - - name: build - run: | - cd $ROVERFLAKE_ROOT - echo $ROS_DISTRO - source /opt/ros/humble/setup.bash - echo $ROS_DISTRO - colcon build --symlink-install --packages-skip sweeppy - - uses: actions/upload-artifact@v4 - with: - name: rover_ws - path: install/ + - uses: actions/checkout@v4 + + - name: enviroment setupg + run: | + export ROVERFLAKE_ROOT="${GITHUB_WORKSPACE}" + yes | ./setup_scripts/setup_everything_common.sh + + - name: build + run: | + cd $ROVERFLAKE_ROOT + echo $ROS_DISTRO + source /opt/ros/humble/setup.bash + echo $ROS_DISTRO + colcon build --symlink-install --packages-skip sweeppy + + - uses: actions/upload-artifact@v4 + with: + name: rover_ws + path: install/ + + - name: Notify Discord (success) + if: ${{ success() }} + uses: appleboy/discord-action@v1.0.0 + with: + webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} + webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} + message: | + *I'm happy now and I'll let you merge ${{ github.actor }}. _good job!_* || ${{ github.repository }} on `${{ github.ref_name }}` + ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + + - name: Notify Discord (failure) + if: ${{ failure() }} + uses: appleboy/discord-action@v1.0.0 + with: + webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} + webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} + message: | + _you have saddened me ${{ github.actor }}_ + ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - - name: Notify Discord (success) - if: ${{ success() }} - uses: appleboy/discord-action@v1.0.0 - with: - webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} # it also accepts full URL - webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} # it also accepts full URL - message: | - *I'm happy now and I'll let you merge ${{ github.actor }}. _good job!_* || ${{ github.repository }} on `${{ github.ref_name }}` - ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - - name: Notify Discord (failure) - if: ${{ failure() }} - uses: appleboy/discord-action@v1.0.0 - with: - webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} # it also accepts full URL - webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} # it also accepts full URL - message: | - _you have saddened me ${{ github.actor }}_ - ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} integration_tests: runs-on: ubuntu-22.04 needs: setup_and_build_check steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 - with: - name: rover_ws - path: install/ - - name: run integration tests - run: | - source install/setup.bash - colcon test --packages-select integration_tests - colcon test-result --verbose - - name: Notify Discord (failure) - if: ${{ failure() }} - uses: appleboy/discord-action@v1.0.0 - with: - webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} # it also accepts full URL - webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} # it also accepts full URL - message: | - _Unit tests have failed ${{ github.actor }}_ - ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - @rowan Check for integration misshaps \ No newline at end of file + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: rover_ws + path: install/ + + - name: run integration tests + run: | + source install/setup.bash + colcon test --packages-select integration_tests + colcon test-result --verbose + + - name: Notify Discord (failure) + if: ${{ failure() }} + uses: appleboy/discord-action@v1.0.0 + with: + webhook_id: ${{ secrets.DISCORD_BOT_WEBHOOK_ID }} + webhook_token: ${{ secrets.DISCORD_BOT_WEBHOOK_TOKEN }} + message: | + _Unit tests have failed ${{ github.actor }}_ + ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + @rowan Check for integration misshaps From 3a2fe483e02715ebd3f5e9b757743b7d7fc1946d Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 19:57:34 -0800 Subject: [PATCH 13/15] retrigger From 5315158747f1d7c2b395ad6d7975ed8b25989d40 Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 20:02:23 -0800 Subject: [PATCH 14/15] work --- .github/workflows/install_and_build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index c7d5859..9caa5bc 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -24,7 +24,7 @@ jobs: - uses: actions/upload-artifact@v4 with: name: rover_ws - path: install/ + path: ${GITHUB_WORKSPACE}/install/ - name: Notify Discord (success) if: ${{ success() }} @@ -55,7 +55,7 @@ jobs: - uses: actions/download-artifact@v4 with: name: rover_ws - path: install/ + path: ${GITHUB_WORKSPACE}/install/ - name: run integration tests run: | From 4f22a283007cd635bec13d045f9a74eb4d034b4f Mon Sep 17 00:00:00 2001 From: Roozki Date: Sun, 30 Nov 2025 20:08:55 -0800 Subject: [PATCH 15/15] fix build errorsg --- .github/workflows/install_and_build.yaml | 1 + src/arm_control/package.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/install_and_build.yaml b/.github/workflows/install_and_build.yaml index 9caa5bc..db29407 100644 --- a/.github/workflows/install_and_build.yaml +++ b/.github/workflows/install_and_build.yaml @@ -59,6 +59,7 @@ jobs: - name: run integration tests run: | + cd ${GITHUB_WORKSPACE} source install/setup.bash colcon test --packages-select integration_tests colcon test-result --verbose diff --git a/src/arm_control/package.xml b/src/arm_control/package.xml index 24b921d..a4e8ae9 100644 --- a/src/arm_control/package.xml +++ b/src/arm_control/package.xml @@ -25,6 +25,7 @@ rover_msgs trajectory_msgs moveit_servo + arm_hardware_interface