Skip to content

Commit b917ab2

Browse files
authored
Merge pull request #549 from JdeRobot/testing
Add Launch Tests and enforce in CI
2 parents 21bc451 + 43b756b commit b917ab2

29 files changed

+1312
-93
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
name: ROS 2 Launch Tests (Gazebo Harmonic)
2+
3+
on:
4+
push:
5+
branches: [main, testing]
6+
pull_request:
7+
branches: [main, testing]
8+
workflow_dispatch:
9+
10+
env:
11+
WORLDS_DIR: /opt/jderobot
12+
ROS_DISTRO: humble
13+
14+
jobs:
15+
launch-tests:
16+
runs-on: ubuntu-22.04
17+
timeout-minutes: 30
18+
19+
steps:
20+
- name: Create checkout directory with proper permissions
21+
run: |
22+
sudo mkdir -p ${{ env.WORLDS_DIR }}
23+
sudo chmod -R 777 ${{ env.WORLDS_DIR }}
24+
25+
- name: Checkout repository
26+
uses: actions/checkout@v3
27+
28+
- name: copy worlds
29+
run: |
30+
sudo cp -r ${{ github.workspace }}/Worlds ${{ env.WORLDS_DIR }}
31+
sudo cp -r ${{ github.workspace }}/jderobot_drones ${{ env.WORLDS_DIR }}
32+
33+
- name: Setup ROS 2 Humble
34+
run: |
35+
# Add the ROS 2 apt repository with updated key
36+
sudo apt-get update && sudo apt-get install -y curl gnupg lsb-release
37+
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
38+
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
39+
sudo apt-get update
40+
# Install ROS 2 packages
41+
sudo apt-get install -y ros-humble-ros-base python3-colcon-common-extensions
42+
43+
- name: "Setup Gazebo"
44+
uses: gazebo-tooling/[email protected]
45+
with:
46+
required-gazebo-distributions: harmonic
47+
- name: "Test Gazebo installation"
48+
run: "gz sim --versions"
49+
50+
- name: Install Gazebo classic and resolve version conflicts
51+
run: |
52+
sudo add-apt-repository ppa:openrobotics/gazebo11-gz-cli
53+
sudo apt update
54+
sudo apt-get install gazebo11
55+
56+
# Resolve version conflicts
57+
sudo apt-get remove libgazebo11
58+
sudo apt-get install libgazebo11=11.10.2+dfsg-1
59+
sudo apt-get install libgazebo-dev
60+
61+
- name: Install aerostack2 and dependencies
62+
run: |
63+
sudo apt-get install -y ros-humble-xacro
64+
sudo apt-get install -y ros-humble-geographic-msgs libgeographic-dev ros-humble-mocap4r2-msgs
65+
sudo apt install git python3-rosdep python3-pip python3-colcon-common-extensions -y
66+
67+
mkdir -p ./aerostack2_ws/src/ && cd ./aerostack2_ws/src/
68+
git clone https://github.com/aerostack2/aerostack2.git
69+
cd ..
70+
sudo rosdep init
71+
rosdep update
72+
rosdep install -y -r -q --from-paths src --ignore-src
73+
sudo apt install ros-humble-ros-gzharmonic
74+
75+
- name: "Test Gazebo installation"
76+
run: "gz sim --versions"
77+
78+
- name: Setup Python dependencies
79+
run: |
80+
python -m pip install --upgrade pip
81+
if [ -f test/requirements.txt ]; then
82+
pip install -r test/requirements.txt
83+
fi
84+
pip install pytest pytest-timeout pytest-cov
85+
86+
- name: Configure Gazebo for headless rendering
87+
run: |
88+
# Configure display for headless rendering
89+
echo "export GAZEBO_IP=127.0.0.1" >> $GITHUB_ENV
90+
echo "export OGRE_RTT_MODE=Copy" >> $GITHUB_ENV
91+
echo "export DISPLAY=:1" >> $GITHUB_ENV
92+
93+
# Configure audio to use null devices
94+
echo "export AUDIODEV=null" >> $GITHUB_ENV
95+
echo "export SDL_AUDIODRIVER=dummy" >> $GITHUB_ENV
96+
97+
# Create dummy ALSA config
98+
echo 'pcm.!default { type null; }' > ~/.asoundrc
99+
echo 'ctl.!default { type null; }' >> ~/.asoundrc
100+
101+
# Set up virtual framebuffer for visual rendering
102+
sudo apt-get install -y xvfb
103+
Xvfb :1 -screen 0 1280x1024x24 &
104+
105+
# Give Xvfb and audio config time to initialize
106+
sleep 3
107+
108+
- name: add only Harmonic tests to ros package
109+
run: sed -i 's|file(GLOB TEST_FILES "${RI_ROOT_DIR}/test/test\*\.py")|file(GLOB TEST_FILES "${RI_ROOT_DIR}/test/harmonic/test_*.py")|' CustomRobots/CMakeLists.txt
110+
111+
- name: Build workspace
112+
run: |
113+
source /opt/ros/humble/setup.bash
114+
colcon build --symlink-install
115+
116+
- name: Rename Launch Files
117+
run: |
118+
cp install/as2_state_estimator/share/as2_state_estimator/launch/ground_truth_state_estimator.launch.py install/as2_state_estimator/share/as2_state_estimator/launch/ground_truth-state_estimator.launch.py
119+
cp install/as2_motion_controller/share/as2_motion_controller/launch/pid_speed_controller.launch.py install/as2_motion_controller/share/as2_motion_controller/launch/pid_speed_controller-motion_controller.launch.py
120+
121+
- name: Run launch tests
122+
run: |
123+
source /opt/ros/humble/setup.bash
124+
source install/setup.bash
125+
colcon test --packages-select custom_robots --event-handlers console_direct+ --return-code-on-test-failure
126+
127+
- name: Show test results
128+
if: always()
129+
run: |
130+
colcon test-result --verbose
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
name: ROS 2 Launch Tests
2+
3+
on:
4+
push:
5+
branches: [main, testing]
6+
pull_request:
7+
branches: [main, testing]
8+
workflow_dispatch:
9+
10+
env:
11+
WORLDS_DIR: /opt/jderobot
12+
ROS_DISTRO: humble
13+
14+
jobs:
15+
launch-tests:
16+
runs-on: ubuntu-22.04
17+
timeout-minutes: 30
18+
19+
steps:
20+
- name: Create checkout directory with proper permissions
21+
run: |
22+
sudo mkdir -p ${{ env.WORLDS_DIR }}
23+
sudo chmod -R 777 ${{ env.WORLDS_DIR }}
24+
25+
- name: Checkout repository
26+
uses: actions/checkout@v3
27+
28+
- name: copy worlds
29+
run: |
30+
sudo cp -r ${{ github.workspace }}/Worlds ${{ env.WORLDS_DIR }}
31+
32+
- name: Setup ROS 2 Humble
33+
run: |
34+
# Add the ROS 2 apt repository with updated key
35+
sudo apt-get update && sudo apt-get install -y curl gnupg lsb-release
36+
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
37+
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
38+
sudo apt-get update
39+
# Install ROS 2 packages
40+
sudo apt-get install -y ros-humble-ros-base python3-colcon-common-extensions
41+
42+
- name: Install Gazebo and dependencies
43+
run: |
44+
# First install libunwind-dev to satisfy dependency requirements
45+
sudo apt-get update
46+
sudo apt-get install -y libunwind-dev
47+
48+
# Then install the rest of the packages
49+
sudo apt-get install -y python3-pip python3-pytest-timeout python3-pytest-cov \
50+
ros-humble-launch-testing ros-humble-launch-testing-ament-cmake \
51+
ros-humble-gazebo-ros-pkgs ros-humble-gazebo-ros ros-humble-xacro \
52+
ros-humble-joint-state-publisher ros-humble-robot-state-publisher \
53+
ros-humble-nav2-msgs ros-humble-turtlebot3-msgs
54+
55+
# Install Gazebo separately with --fix-broken option
56+
sudo apt-get install -y --fix-broken gazebo libgazebo-dev
57+
58+
- name: Setup Python dependencies
59+
run: |
60+
python -m pip install --upgrade pip
61+
if [ -f test/requirements.txt ]; then
62+
pip install -r test/requirements.txt
63+
fi
64+
pip install pytest pytest-timeout pytest-cov
65+
66+
- name: Configure Gazebo for headless rendering
67+
run: |
68+
# Configure display for headless rendering
69+
echo "export GAZEBO_IP=127.0.0.1" >> $GITHUB_ENV
70+
echo "export OGRE_RTT_MODE=Copy" >> $GITHUB_ENV
71+
echo "export DISPLAY=:1" >> $GITHUB_ENV
72+
73+
# Configure audio to use null devices
74+
echo "export AUDIODEV=null" >> $GITHUB_ENV
75+
echo "export SDL_AUDIODRIVER=dummy" >> $GITHUB_ENV
76+
77+
# Create dummy ALSA config
78+
echo 'pcm.!default { type null; }' > ~/.asoundrc
79+
echo 'ctl.!default { type null; }' >> ~/.asoundrc
80+
81+
# Set up virtual framebuffer for visual rendering
82+
sudo apt-get install -y xvfb
83+
Xvfb :1 -screen 0 1280x1024x24 &
84+
85+
# Give Xvfb and audio config time to initialize
86+
sleep 3
87+
88+
- name: Build workspace
89+
run: |
90+
source /opt/ros/humble/setup.bash
91+
source /usr/share/gazebo/setup.sh
92+
colcon build --symlink-install --packages-up-to custom_robots
93+
94+
- name: Run launch tests
95+
run: |
96+
source /opt/ros/humble/setup.bash
97+
source install/setup.bash
98+
source /usr/share/gazebo/setup.bash
99+
colcon test --packages-select custom_robots --event-handlers console_direct+ --return-code-on-test-failure
100+
101+
- name: Show test results
102+
if: always()
103+
run: |
104+
colcon test-result --verbose

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,12 @@ __pycache__/
44

55
# IDEs
66
.vscode
7+
8+
# Tests
9+
build
10+
install
11+
test/__pycache__/
12+
13+
# Logs
14+
**log**
15+

CustomRobots/CMakeLists.txt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
cmake_minimum_required(VERSION 3.8)
22
project(custom_robots)
33

4+
# Define project root directory
5+
set(RI_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..)
6+
47
# Default to C99
58
if(NOT CMAKE_C_STANDARD)
69
set(CMAKE_C_STANDARD 99)
@@ -137,9 +140,22 @@ install(
137140
pick_place/urdf
138141
DESTINATION share/${PROJECT_NAME})
139142

143+
install(
144+
FILES ${RI_ROOT_DIR}/Launchers/follow_road.launch.py
145+
${RI_ROOT_DIR}/Launchers/rescue_people.launch.py
146+
DESTINATION share/${PROJECT_NAME}/launch)
147+
140148
if(BUILD_TESTING)
141-
find_package(ament_lint_auto REQUIRED)
142-
ament_lint_auto_find_test_dependencies()
149+
# find_package(ament_lint_auto REQUIRED)
150+
# ament_lint_auto_find_test_dependencies()
151+
152+
find_package(launch_testing_ament_cmake REQUIRED)
153+
# Use file(GLOB...) to find all test files matching the pattern
154+
file(GLOB TEST_FILES "${RI_ROOT_DIR}/test/test*.py")
155+
# Loop through each test file and add it as a launch test
156+
foreach(test_file ${TEST_FILES})
157+
add_launch_test(${test_file} TIMEOUT 90)
158+
endforeach()
143159
endif()
144160

145161
ament_export_libraries(personplugin)

CustomRobots/car_junction/launch/car_junction.launch.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,22 @@ def generate_launch_description():
2626
"GAZEBO_MODEL_PATH"
2727
] = f"{os.environ.get('GAZEBO_MODEL_PATH', '')}:{':'.join(gazebo_models_path)}"
2828

29-
start_ros_gazebo_bridge = Node(
30-
package="ros_gz_bridge",
31-
executable="parameter_bridge",
32-
arguments=[
33-
"/clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock",
34-
"/cmd_vel@geometry_msgs/msg/Twist]gz.msgs.Twist",
35-
"/odom@nav_msgs/msg/Odometry]gz.msgs.Odometry",
36-
"/waymo/lidar/points@sensor_msgs/msg/PointCloud2[gz.msgs.PointCloudPacked",
37-
"/waymo/camera_info@sensor_msgs/msg/CameraInfo[gz.msgs.CameraInfo",
38-
],
39-
parameters=[{'use_sim_time': True}],
40-
output="screen"
41-
),
42-
29+
start_ros_gazebo_bridge = (
30+
Node(
31+
package="ros_gz_bridge",
32+
executable="parameter_bridge",
33+
arguments=[
34+
"/clock@rosgraph_msgs/msg/Clock[gz.msgs.Clock",
35+
"/cmd_vel@geometry_msgs/msg/Twist]gz.msgs.Twist",
36+
"/odom@nav_msgs/msg/Odometry]gz.msgs.Odometry",
37+
"/waymo/lidar/points@sensor_msgs/msg/PointCloud2[gz.msgs.PointCloudPacked",
38+
"/waymo/camera_info@sensor_msgs/msg/CameraInfo[gz.msgs.CameraInfo",
39+
],
40+
parameters=[{"use_sim_time": True}],
41+
output="screen",
42+
),
43+
)
44+
4345
start_ros_gazebo_image_bridge = Node(
4446
package="ros_gz_image",
4547
executable="image_bridge",

0 commit comments

Comments
 (0)