Skip to content

Commit

Permalink
changed rosbot_xl_controller to ament_python pakcage | added tests fr…
Browse files Browse the repository at this point in the history
…om rosbot_ros

Signed-off-by: Jakub Delicat <jakub.delicat@husarion.com>
  • Loading branch information
delihus committed Oct 19, 2023
1 parent 2f76033 commit 5f1ead3
Show file tree
Hide file tree
Showing 13 changed files with 456 additions and 16 deletions.
12 changes: 0 additions & 12 deletions rosbot_xl_controller/CMakeLists.txt

This file was deleted.

5 changes: 4 additions & 1 deletion rosbot_xl_controller/launch/controller.launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ def generate_launch_description():
declare_mecanum_arg = DeclareLaunchArgument(
"mecanum",
default_value="False",
description="Whether to use mecanum drive controller (otherwise diff drive controller is used)",
description=(
"Whether to use mecanum drive controller"
"(otherwise diff drive controller is used)",
)
)

lidar_model = LaunchConfiguration("lidar_model")
Expand Down
5 changes: 2 additions & 3 deletions rosbot_xl_controller/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@

<author email="maciej.stepien@husarion.com">Maciej Stepien</author>
<author email="krzysztof.wojciechowski@husarion.com">Krzysztof Wojciechowski</author>
<author email="jakub.delicat@husarion.com">Jakub Delicat</author>
<maintainer email="support@husarion.com">Husarion</maintainer>

<url type="website">https://husarion.com/</url>
<url type="repository">https://github.com/husarion/rosbot_xl_ros</url>
<url type="bugtracker">https://github.com/husarion/rosbot_xl_ros/issues</url>

<buildtool_depend>ament_cmake</buildtool_depend>

<exec_depend>rosbot_xl_description</exec_depend>

<exec_depend>launch</exec_depend>
Expand All @@ -34,6 +33,6 @@
<exec_depend>rosbot_hardware_interfaces</exec_depend>

<export>
<build_type>ament_cmake</build_type>
<build_type>ament_python</build_type>
</export>
</package>
Empty file.
4 changes: 4 additions & 0 deletions rosbot_xl_controller/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[develop]
script_dir=$base/lib/rosbot_xl_controller
[install]
install_scripts=$base/lib/rosbot_xl_controller
27 changes: 27 additions & 0 deletions rosbot_xl_controller/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os
from glob import glob
from setuptools import find_packages, setup

package_name = "rosbot_xl_controller"

setup(
name=package_name,
version="0.8.2",
packages=find_packages(exclude=["test"]),
data_files=[
("share/ament_index/resource_index/packages", ["resource/" + package_name]),
("share/" + package_name, ["package.xml"]),
(os.path.join("share", package_name, "launch"), glob("launch/*.launch.py")),
(os.path.join("share", package_name, "config"), glob("config/*.yaml")),
],
install_requires=["setuptools"],
zip_safe=True,
maintainer="Husarion",
maintainer_email="contact@husarion.com",
description="Hardware configuration for ROSbot XL",
license="Apache License 2.0",
tests_require=["pytest"],
entry_points={
"console_scripts": [],
},
)
97 changes: 97 additions & 0 deletions rosbot_xl_controller/test/controllers_test_node.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Copyright 2021 Open Source Robotics Foundation, Inc.
# Copyright 2023 Husarion
#
# 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.

import rclpy

from threading import Event
from threading import Thread

from rclpy.node import Node

from sensor_msgs.msg import JointState, Imu
from nav_msgs.msg import Odometry


class ControllersTestNode(Node):
ROSBOT_HARDWARE_PUBLISHERS_RATE = 10.0

__test__ = False

def __init__(self, name="test_node"):
super().__init__(name)
self.joint_state_msg_event = Event()
self.odom_msg_event = Event()
self.imu_msg_event = Event()

def create_test_subscribers_and_publishers(self):
self.joint_state_sub = self.create_subscription(
JointState, "/joint_states", self.joint_states_callback, 10
)

self.odom_sub = self.create_subscription(
Odometry, "/rosbot_xl_base_controller/odom", self.odometry_callback, 10
)

self.imu_sub = self.create_subscription(
Imu, "/imu_broadcaster/imu", self.imu_callback, 10
)

self.imu_publisher = self.create_publisher(Imu, "_imu/data_raw", 10)

self.joint_states_publisher = self.create_publisher(
JointState, "_motors_response", 10
)

self.timer = None

def start_node_thread(self):
self.ros_spin_thread = Thread(
target=lambda node: rclpy.spin(node), args=(self,)
)
self.ros_spin_thread.start()

def joint_states_callback(self, data):
self.joint_state_msg_event.set()

def odometry_callback(self, data):
self.odom_msg_event.set()

def imu_callback(self, data):
self.imu_msg_event.set()

def start_publishing_fake_hardware(self):
self.timer = self.create_timer(
1.0 / self.ROSBOT_HARDWARE_PUBLISHERS_RATE,
self.publish_fake_hardware_messages,
)

def publish_fake_hardware_messages(self):
imu_msg = Imu()
imu_msg.header.stamp = self.get_clock().now().to_msg()
imu_msg.header.frame_id = "imu_link"

joint_state_msg = JointState()
joint_state_msg.header.stamp = self.get_clock().now().to_msg()
joint_state_msg.name = [
"fl_wheel_joint",
"fr_wheel_joint",
"rl_wheel_joint",
"rr_wheel_joint",
]
joint_state_msg.position = [0.0, 0.0, 0.0, 0.0]
joint_state_msg.velocity = [0.0, 0.0, 0.0, 0.0]

self.imu_publisher.publish(imu_msg)
self.joint_states_publisher.publish(joint_state_msg)
23 changes: 23 additions & 0 deletions rosbot_xl_controller/test/test_copyright.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 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"
98 changes: 98 additions & 0 deletions rosbot_xl_controller/test/test_diff_drive_controllers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Copyright 2021 Open Source Robotics Foundation, Inc.
# Copyright 2023 Intel Corporation. All Rights Reserved.
# Copyright 2023 Husarion
#
# 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.

import launch_pytest
import pytest
import rclpy

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.substitutions import PathJoinSubstitution
from launch.launch_description_sources import PythonLaunchDescriptionSource
from controllers_test_node import ControllersTestNode


@launch_pytest.fixture
def generate_test_description():
rosbot_xl_controller = get_package_share_directory("rosbot_xl_controller")
bringup_launch = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
PathJoinSubstitution(
[
rosbot_xl_controller,
"launch",
"controller.launch.py",
]
)
),
launch_arguments={
"use_sim": "False",
"mecanum": "False",
"use_gpu": "False",
}.items(),
)

return LaunchDescription([bringup_launch])


@pytest.mark.launch(fixture=generate_test_description)
def test_controllers_startup_fail():
rclpy.init()
try:
node = ControllersTestNode("test_controllers_bringup")
node.create_test_subscribers_and_publishers()

node.start_node_thread()
msgs_received_flag = node.joint_state_msg_event.wait(timeout=10.0)
assert (
not msgs_received_flag
), "Expected JointStates message not received. Check joint_state_broadcaster!"
msgs_received_flag = node.odom_msg_event.wait(timeout=10.0)
assert (
not msgs_received_flag
), "Expected Odom message not received. Check rosbot_base_controller!"
msgs_received_flag = node.imu_msg_event.wait(timeout=10.0)
assert (
not msgs_received_flag
), "Expected Imu message not received. Check imu_broadcaster!"
finally:
rclpy.shutdown()


@pytest.mark.launch(fixture=generate_test_description)
def test_controllers_startup_success():
rclpy.init()
try:
node = ControllersTestNode("test_controllers_bringup")
node.create_test_subscribers_and_publishers()
node.start_publishing_fake_hardware()

node.start_node_thread()
msgs_received_flag = node.joint_state_msg_event.wait(timeout=10.0)
assert (
msgs_received_flag
), "Expected JointStates message but it was not received. Check joint_state_broadcaster!"
msgs_received_flag = node.odom_msg_event.wait(timeout=10.0)
assert (
msgs_received_flag
), "Expected Odom message but it was not received. Check rosbot_base_controller!"
msgs_received_flag = node.imu_msg_event.wait(timeout=10.0)
assert (
msgs_received_flag
), "Expected Imu message but it was not received. Check imu_broadcaster!"
finally:
rclpy.shutdown()
25 changes: 25 additions & 0 deletions rosbot_xl_controller/test/test_flake8.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 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


@pytest.mark.flake8
@pytest.mark.linter
def test_flake8():
rc, errors = main_with_errors(argv=[])
assert rc == 0, "Found %d code style errors / warnings:\n" % len(
errors
) + "\n".join(errors)
Loading

0 comments on commit 5f1ead3

Please sign in to comment.