Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ROSbot 2R, XL webots_ros2 support #770

Merged
merged 45 commits into from
Aug 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
de0c3f4
new ROSbots configuration
delihus Jun 9, 2023
cb40ee3
Merge remote-tracking branch 'upstream/develop' into develop-husarion
delihus Jun 9, 2023
43fd8c3
remove submodules
delihus Jun 9, 2023
e1dec69
updated submodules
delihus Jun 9, 2023
872aa1c
Skip rosbots submodules in tests
delihus Jun 9, 2023
77ad619
updated version
delihus Jun 9, 2023
a6b1a66
launch update
delihus Jun 9, 2023
cfa253b
remove test lidar include
delihus Jun 9, 2023
f5474e2
removed submodules
delihus Jun 22, 2023
b8be71c
removed husarion deps
delihus Jun 22, 2023
e406812
Merge remote-tracking branch 'upstream/master' into develop-husarion
delihus Jun 22, 2023
6dba975
added urdf | added tests
delihus Jun 22, 2023
515e81f
lint fix
delihus Jun 22, 2023
70becbd
changed arg description
delihus Jun 23, 2023
fce636a
added webots_ros2_husarion to dependencies
delihus Jun 23, 2023
b59e9c4
added ros2 controls deps
delihus Jun 23, 2023
71746d8
test username var
delihus Jun 23, 2023
6546f54
Merge remote-tracking branch 'upstream/master' into develop-husarion
delihus Jul 4, 2023
d8e7e34
apply links remapping
delihus Jul 5, 2023
9148907
added to test checking the sensor fusion
delihus Jul 5, 2023
c0aa1fa
removed quotes
delihus Jul 5, 2023
5b39ae5
changed .protos paths
delihus Jul 6, 2023
3618dc2
Merge remote-tracking branch 'upstream/master' into develop-husarion
delihus Jul 7, 2023
069dab0
removed remappings
delihus Jul 11, 2023
260627f
test installing robot_localization
delihus Jul 11, 2023
7923f11
Revert "test installing robot_localization"
delihus Jul 11, 2023
1297aea
Merge remote-tracking branch 'upstream/master' into develop-husarion
delihus Jul 11, 2023
8eefeb3
changed odom test to listen diff drive controller
delihus Jul 11, 2023
d88b515
check movement ROSbot and scan on ROSbot XL
delihus Jul 11, 2023
206679b
removed unused includes
delihus Jul 11, 2023
7d7d8b2
added debug log
delihus Jul 11, 2023
6a9d204
fix sources
delihus Jul 11, 2023
4a580a8
laser print debug
delihus Jul 11, 2023
5669398
inf or nan scan implementation
delihus Jul 11, 2023
cd00eec
back logs
delihus Jul 11, 2023
38825c6
added math.isnan
delihus Jul 11, 2023
48ccaf2
Merge remote-tracking branch 'upstream/master' into develop-husarion
delihus Jul 12, 2023
da67d27
added covariances
delihus Jul 12, 2023
d076936
added covariance to ROSbot XL
delihus Jul 12, 2023
053d4f4
fixed ekf for humble
delihus Jul 14, 2023
172dd71
removed debug logs
delihus Jul 14, 2023
75084e6
apply linting review
delihus Jul 17, 2023
bbb5f57
Update webots_ros2_husarion/CHANGELOG.rst
delihus Jul 17, 2023
7640dd7
updated main CHANGELOG.rst
delihus Jul 17, 2023
23bfbbb
Merge branch 'develop' into develop-husarion
delihus Jul 31, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tests/sources/test_clang_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def test_sources_are_clang_format_compliant(self):
'webots_ros2_control',
'webots_ros2_driver',
'webots_ros2_epuck',
'webots_ros2_husarion',
'webots_ros2_importer',
'webots_ros2_mavic',
'webots_ros2_msgs',
Expand Down
5 changes: 4 additions & 1 deletion tests/sources/test_pep8.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@
skippedDirectories = [
'.git',
'webots_ros2_importer/webots_ros2_importer/urdf2webots/',
'webots_ros2_driver/webots/lib'
'webots_ros2_driver/webots/lib',
'webots_ros2_husarion/rosbot_ros',
'webots_ros2_husarion/rosbot_xl_ros',
'webots_ros2_husarion/ros_components_description'
]
skippedDirectoriesFull = [os.path.join(ROOT_FOLDER, os.path.normpath(path)) for path in skippedDirectories]

Expand Down
4 changes: 4 additions & 0 deletions webots_ros2/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
Changelog for package webots_ros2
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

2024.0.0 (2023-XX-XX)
------------------
* Created webots_ros2_husarion package.

2023.1.1 (2023-07-11)
------------------
* Added deprecation message when declaring driver node in launch file.
Expand Down
7 changes: 7 additions & 0 deletions webots_ros2_husarion/CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changelog for package webots_ros2_husarion
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

2024.0.0 (2023-XX-XX)
------------------
* Created webots_ros2_husarion package.
167 changes: 167 additions & 0 deletions webots_ros2_husarion/launch/rosbot_launch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#!/usr/bin/env python

# Copyright 1996-2023 Cyberbotics Ltd.
# 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.

"""Launch Webots ROSbot 2R driver."""

import os
import launch
from launch.substitutions import LaunchConfiguration
from launch.actions import DeclareLaunchArgument
from launch.substitutions.path_join_substitution import PathJoinSubstitution
from launch import LaunchDescription
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
from webots_ros2_driver.webots_launcher import WebotsLauncher
from webots_ros2_driver.webots_controller import WebotsController
from webots_ros2_driver.wait_for_controller_connection import WaitForControllerConnection


def get_ros2_nodes(*args):
package_dir = get_package_share_directory('webots_ros2_husarion')
robot_description_path = os.path.join(package_dir, 'resource', 'rosbot_webots.urdf')
links_remappings_file_path = os.path.join(package_dir, 'resource', 'rosbot_links_remappings.yaml')

ekf_config = os.path.join(package_dir, 'resource', 'ekf.yaml')

ros2_control_params = os.path.join(package_dir, 'resource', 'rosbot_controllers.yaml')
use_sim_time = LaunchConfiguration('use_sim_time', default=True)

# ROS control spawners
controller_manager_timeout = ['--controller-manager-timeout', '50']
controller_manager_prefix = 'python.exe' if os.name == 'nt' else ''
diff_drive_controller_spawner = Node(
package='controller_manager',
executable='spawner',
output='screen',
prefix=controller_manager_prefix,
arguments=['rosbot_base_controller'] + controller_manager_timeout,
)
joint_state_broadcaster_spawner = Node(
package='controller_manager',
executable='spawner',
output='screen',
prefix=controller_manager_prefix,
arguments=['joint_state_broadcaster'] + controller_manager_timeout,
)
ros_control_spawners = [diff_drive_controller_spawner, joint_state_broadcaster_spawner]

rosbot_driver = WebotsController(
robot_name='rosbot',
parameters=[
{
'robot_description': robot_description_path,
'use_sim_time': use_sim_time,
'set_robot_state_publisher': True,
},
ros2_control_params,
{'components_remappings': links_remappings_file_path}
],
remappings=[
('rosbot_base_controller/cmd_vel_unstamped', '/cmd_vel'),
('rosbot/laser', '/scan'),
('rosbot/rl_range', '/range/rl'),
('rosbot/rr_range', '/range/rr'),
('rosbot/fl_range', '/range/fl'),
('rosbot/fr_range', '/range/fr')
],
)

robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
output='screen',
parameters=[{
'robot_description': '<robot name=""><link name=""/></robot>'
}],
)

robot_localization_node = Node(
package='robot_localization',
executable='ekf_node',
name='ekf_filter_node',
output='screen',
parameters=[
ekf_config,
{'use_sim_time': True},
{'odom0': '/rosbot_base_controller/odom'}
]
)

# Wait for the simulation to be ready to start navigation nodes
waiting_nodes = WaitForControllerConnection(
target_driver=rosbot_driver,
nodes_to_start=ros_control_spawners
)

return [
robot_state_publisher,
rosbot_driver,
waiting_nodes,
robot_localization_node
]


def generate_launch_description():
package_dir = get_package_share_directory('webots_ros2_husarion')
world = LaunchConfiguration('world')
mode = LaunchConfiguration('mode')

webots = WebotsLauncher(
world=PathJoinSubstitution([package_dir, 'worlds', world]),
mode=mode,
ros2_supervisor=True
)

# The following line is important!
# This event handler respawns the ROS 2 nodes on simulation reset (supervisor process ends).
reset_handler = launch.actions.RegisterEventHandler(
event_handler=launch.event_handlers.OnProcessExit(
target_action=webots._supervisor,
on_exit=get_ros2_nodes,
)
)

return LaunchDescription([
DeclareLaunchArgument(
'world',
default_value='rosbot.wbt',
description='Choose one of the world files from `/webots_ros2_husarion/world` directory'
),
DeclareLaunchArgument(
'mode',
default_value='realtime',
description='Webots startup mode'
),
webots,
webots._supervisor,

# This action will kill all nodes once the Webots simulation has exited
launch.actions.RegisterEventHandler(
event_handler=launch.event_handlers.OnProcessExit(
target_action=webots,
on_exit=[
launch.actions.UnregisterEventHandler(
event_handler=reset_handler.event_handler
),
launch.actions.EmitEvent(event=launch.events.Shutdown())
],
)
),

# Add the reset event handler
reset_handler
] + get_ros2_nodes())
168 changes: 168 additions & 0 deletions webots_ros2_husarion/launch/rosbot_xl_launch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#!/usr/bin/env python

# Copyright 1996-2023 Cyberbotics Ltd.
# 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.

"""Launch Webots ROSbot XL driver."""

import os
import launch
from launch.substitutions import LaunchConfiguration
from launch.actions import DeclareLaunchArgument
from launch.substitutions.path_join_substitution import PathJoinSubstitution
from launch import LaunchDescription
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
from webots_ros2_driver.webots_launcher import WebotsLauncher
from webots_ros2_driver.webots_controller import WebotsController
from webots_ros2_driver.wait_for_controller_connection import WaitForControllerConnection


def get_ros2_nodes(*args):
package_dir = get_package_share_directory('webots_ros2_husarion')
robot_description_path = os.path.join(package_dir, 'resource', 'rosbot_webots.urdf')
laser_filter_config = os.path.join(package_dir, 'resource', 'laser_filter.yaml')
ekf_config = os.path.join(package_dir, 'resource', 'ekf.yaml')
links_remappings_file_path = os.path.join(package_dir, 'resource', 'rosbot_links_remappings.yaml')

ros2_control_params = os.path.join(package_dir, 'resource', 'rosbot_xl_controllers.yaml')
use_sim_time = LaunchConfiguration('use_sim_time', default=True)

# ROS control spawners
controller_manager_timeout = ['--controller-manager-timeout', '50']
controller_manager_prefix = 'python.exe' if os.name == 'nt' else ''
diff_drive_controller_spawner = Node(
package='controller_manager',
executable='spawner',
output='screen',
prefix=controller_manager_prefix,
arguments=['rosbot_xl_base_controller'] + controller_manager_timeout,
)
joint_state_broadcaster_spawner = Node(
package='controller_manager',
executable='spawner',
output='screen',
prefix=controller_manager_prefix,
arguments=['joint_state_broadcaster'] + controller_manager_timeout,
)
ros_control_spawners = [diff_drive_controller_spawner, joint_state_broadcaster_spawner]

rosbot_driver = WebotsController(
robot_name='rosbot_xl',
parameters=[
{'robot_description': robot_description_path,
'use_sim_time': use_sim_time,
'set_robot_state_publisher': True},
ros2_control_params,
{'components_remappings': links_remappings_file_path}
],
remappings=[
('rosbot_xl_base_controller/cmd_vel_unstamped', '/cmd_vel'),
('rosbot_xl/laser', '/scan')
]
)

robot_state_publisher = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
output='screen',
parameters=[{
'robot_description': '<robot name=""><link name=""/></robot>'
}],
)

robot_localization_node = Node(
package='robot_localization',
executable='ekf_node',
name='ekf_filter_node',
output='screen',
parameters=[
ekf_config,
{'use_sim_time': True},
{'odom0': '/rosbot_xl_base_controller/odom'}
]
)

laser_filter_node = Node(
package='laser_filters',
executable='scan_to_scan_filter_chain',
parameters=[laser_filter_config],
)

# Wait for the simulation to be ready to start navigation nodes
waiting_nodes = WaitForControllerConnection(
target_driver=rosbot_driver,
nodes_to_start=ros_control_spawners
)

return [
robot_state_publisher,
rosbot_driver,
waiting_nodes,
robot_localization_node,
laser_filter_node
]


def generate_launch_description():
package_dir = get_package_share_directory('webots_ros2_husarion')
world = LaunchConfiguration('world')
mode = LaunchConfiguration('mode')

webots = WebotsLauncher(
world=PathJoinSubstitution([package_dir, 'worlds', world]),
mode=mode,
ros2_supervisor=True
)

# The following line is important!
# This event handler respawns the ROS 2 nodes on simulation reset (supervisor process ends).
reset_handler = launch.actions.RegisterEventHandler(
event_handler=launch.event_handlers.OnProcessExit(
target_action=webots._supervisor,
on_exit=get_ros2_nodes,
)
)

return LaunchDescription([
DeclareLaunchArgument(
'world',
default_value='rosbot_xl.wbt',
description='Choose one of the world files from `/webots_ros2_husarion/world` directory'
),
DeclareLaunchArgument(
'mode',
default_value='realtime',
description='Webots startup mode'
),
webots,
webots._supervisor,

# This action will kill all nodes once the Webots simulation has exited
launch.actions.RegisterEventHandler(
event_handler=launch.event_handlers.OnProcessExit(
target_action=webots,
on_exit=[
launch.actions.UnregisterEventHandler(
event_handler=reset_handler.event_handler
),
launch.actions.EmitEvent(event=launch.events.Shutdown())
],
)
),

# Add the reset event handler
reset_handler
] + get_ros2_nodes())
Loading