diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 000000000..104d9528c
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,32 @@
+on:
+ pull_request:
+ types: [opened, synchronize, reopened, labeled, unlabeled]
+
+env:
+ WEBOTS_VERSION: 2021b
+ WEBOTS_OFFSCREEN: 1
+ CI: 1
+ DEBIAN_FRONTEND: noninteractive
+ QTWEBENGINE_DISABLE_SANDBOX: 1
+
+jobs:
+ ros2:
+ name: Build and test ROS 2 packages
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+ - name: Install ROS2
+ uses: ros-tooling/setup-ros@v0.2
+ with:
+ required-ros-distributions: foxy
+ - name: Install Webots
+ run: |
+ sudo -E apt-get update
+ sudo -E apt-get install -y wget dialog apt-utils psmisc
+ wget "https://github.com/cyberbotics/webots/releases/download/R$WEBOTS_VERSION/webots_${WEBOTS_VERSION}_amd64.deb"
+ sudo -E apt-get install -y "./webots_${WEBOTS_VERSION}_amd64.deb" xvfb
+ - name: Build packages and run and tests
+ uses: ros-tooling/action-ros-ci@v0.2
+ with:
+ target-ros2-distro: foxy
diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml
new file mode 100644
index 000000000..0f2bd18c6
--- /dev/null
+++ b/.github/workflows/linter.yml
@@ -0,0 +1,24 @@
+on:
+ pull_request:
+ types: [opened, synchronize, reopened, labeled, unlabeled]
+
+jobs:
+ linter:
+ name: Check code using Ament linter
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ linter: [flake8, pep257, xmllint]
+ package: [mep3_driver, mep3_simulation]
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+ - name: Install ROS2
+ uses: ros-tooling/setup-ros@v0.2
+ - name: Run ${{ matrix.linter }} linter for ${{ matrix.package }}
+ uses: ros-tooling/action-ros-lint@v0.1
+ with:
+ distribution: foxy
+ linter: ${{ matrix.linter }}
+ package-name: ${{ matrix.package }}
diff --git a/.gitignore b/.gitignore
index 93c700e85..8182863a9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,6 @@
.vscode/
.idea/
+build/
+install/
+log/
+**.pyc
diff --git a/README.md b/README.md
index cafa318f6..7fca096de 100644
--- a/README.md
+++ b/README.md
@@ -56,4 +56,13 @@ ros2 run teleop_twist_keyboard teleop_twist_keyboard
To launch simulation with `rviz` and `nav2` run
```sh
ros2 launch mep3_simulation robot_launch.py rviz:=true nav:=true
-```
\ No newline at end of file
+```
+
+## Testing
+
+- Change working directory to `foxy_ws`
+- Run the following command:
+```sh
+source /opt/ros/foxy/local_setup.bash
+colcon test --event-handlers console_cohesion+ --return-code-on-test-failure
+```
diff --git a/mep3_driver/launch/driver_launch.py b/mep3_driver/launch/driver_launch.py
index 951ea9fbc..7bc1e30e5 100644
--- a/mep3_driver/launch/driver_launch.py
+++ b/mep3_driver/launch/driver_launch.py
@@ -1,19 +1,22 @@
import os
import pathlib
-from launch import LaunchDescription
+
from ament_index_python.packages import get_package_share_directory
+from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
package_dir = get_package_share_directory('mep3_driver')
- robot_description = pathlib.Path(os.path.join(package_dir, 'resource', 'mep3_big_config.urdf')).read_text()
- ros2_control_params = os.path.join(package_dir, 'resource', 'mep3_big_ros2_control.yaml')
+ robot_description = pathlib.Path(os.path.join(
+ package_dir, 'resource', 'mep3_big_config.urdf')).read_text()
+ ros2_control_params = os.path.join(
+ package_dir, 'resource', 'mep3_big_ros2_control.yaml')
controller_manager_node = Node(
- package="controller_manager",
- executable="ros2_control_node",
+ package='controller_manager',
+ executable='ros2_control_node',
parameters=[
{'robot_description': robot_description},
ros2_control_params
diff --git a/mep3_driver/package.xml b/mep3_driver/package.xml
index ee6ca9282..be9f53b73 100644
--- a/mep3_driver/package.xml
+++ b/mep3_driver/package.xml
@@ -16,6 +16,8 @@
ament_lint_auto
ament_lint_common
+ ament_flake8
+ ament_pep257
ament_cmake
diff --git a/mep3_simulation/launch/robot_launch.py b/mep3_simulation/launch/robot_launch.py
index 6ce7cc32c..c2d866b48 100644
--- a/mep3_simulation/launch/robot_launch.py
+++ b/mep3_simulation/launch/robot_launch.py
@@ -1,11 +1,12 @@
import os
import pathlib
+
+from ament_index_python.packages import get_package_share_directory
import launch
-from launch_ros.actions import Node
-from launch.substitutions import LaunchConfiguration
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
-from ament_index_python.packages import get_package_share_directory
+from launch.substitutions import LaunchConfiguration
+from launch_ros.actions import Node
from webots_ros2_core.webots_launcher import WebotsLauncher
@@ -41,11 +42,12 @@ def generate_launch_description():
arguments=['joint_state_broadcaster'] + controller_manager_timeout,
)
- # The node which interacts with a robot in the Webots simulation is located in the
- # `webots_ros2_driver` package under name `driver`.
+ # The node which interacts with a robot in the Webots simulation is located
+ # in the `webots_ros2_driver` package under name `driver`.
# It is necessary to run such a node for each robot in the simulation.
- # Typically, we provide it the `robot_description` parameters from a URDF file and
- # `ros2_control_params` from the `ros2_control` configuration file.
+ # Typically, we provide it the `robot_description` parameters from a URDF
+ # file and `ros2_control_params` from the `ros2_control`
+ # configuration file.
webots_robot_driver = Node(
package='webots_ros2_driver',
executable='driver',
@@ -58,13 +60,13 @@ def generate_launch_description():
]
)
- # Often we want to publish robot transforms, so we use the `robot_state_publisher`
- # node for that.
- # If robot model is not specified in the URDF file then Webots can help us with the
- # URDF exportation feature.
- # Since the exportation feature is available only once the simulation has started and
- # the `robot_state_publisher` node requires a `robot_description` parameter before we
- # have to specify a dummy robot.
+ # Often we want to publish robot transforms, so we use the
+ # `robot_state_publisher` node for that.
+ # If robot model is not specified in the URDF file then Webots can help
+ # us with the URDF exportation feature.
+ # Since the exportation feature is available only once the simulation has
+ # started and the `robot_state_publisher` node requires a
+ # `robot_description` parameter before we have to specify a dummy robot.
robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
diff --git a/mep3_simulation/package.xml b/mep3_simulation/package.xml
index cda3e919f..e3116f6dc 100644
--- a/mep3_simulation/package.xml
+++ b/mep3_simulation/package.xml
@@ -9,7 +9,6 @@
webots_ros2_driver
webots_ros2_control
robot_state_publisher
- ament_copyright
ament_flake8
ament_pep257
python3-pytest
diff --git a/mep3_simulation/setup.py b/mep3_simulation/setup.py
index 2bf16c7c8..28639ab16 100644
--- a/mep3_simulation/setup.py
+++ b/mep3_simulation/setup.py
@@ -1,7 +1,9 @@
-from setuptools import setup
from glob import glob
import os
+from setuptools import setup
+
+
package_name = 'mep3_simulation'
data = {
@@ -18,15 +20,18 @@
}
-def files_in_directory(dir, extension=None):
+def files_in_directory(path, extension=None):
files = []
- for i in os.listdir(dir):
- if not os.path.isdir(f'{dir}/{i}') and (extension is None or i.endswith(extension)):
- files.append(f'{dir}/{i}')
+ for i in os.listdir(path):
+ if not os.path.isdir(f'{path}/{i}') and \
+ (extension is None or i.endswith(extension)):
+ files.append(f'{path}/{i}')
return files
data_files = []
+
+
data_files.extend([
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
diff --git a/mep3_simulation/test/test_copyright.py b/mep3_simulation/test/test_copyright.py
deleted file mode 100644
index cc8ff03f7..000000000
--- a/mep3_simulation/test/test_copyright.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright 2015 Open Source Robotics Foundation, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-from ament_copyright.main import main
-import pytest
-
-
-@pytest.mark.copyright
-@pytest.mark.linter
-def test_copyright():
- rc = main(argv=['.', 'test'])
- assert rc == 0, 'Found errors'
diff --git a/mep3_simulation/test/test_flake8.py b/mep3_simulation/test/test_flake8.py
index 27ee1078f..63b55be7a 100644
--- a/mep3_simulation/test/test_flake8.py
+++ b/mep3_simulation/test/test_flake8.py
@@ -1,17 +1,3 @@
-# Copyright 2017 Open Source Robotics Foundation, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
from ament_flake8.main import main_with_errors
import pytest
diff --git a/mep3_simulation/test/test_pep257.py b/mep3_simulation/test/test_pep257.py
index b234a3840..4795382c6 100644
--- a/mep3_simulation/test/test_pep257.py
+++ b/mep3_simulation/test/test_pep257.py
@@ -1,17 +1,3 @@
-# Copyright 2015 Open Source Robotics Foundation, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
from ament_pep257.main import main
import pytest