diff --git a/README.md b/README.md index 908cf98972388008a8424227f8eb404a1c2d60b7..06110bcbf403c6da73da18395894277c7d175d46 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,13 @@ -# Navigation2 +# Navigation2 Stack -ROS2 Navigation System -[](https://circleci.com/gh/ros-planning/navigation2/tree/master) CircleCI +| Builder | Status | +|----------------------|-------------------------| +| CircleCI | [](https://circleci.com/gh/ros-planning/navigation2/tree/master) | +| DockerHub | [](https://hub.docker.com/r/rosplanning/navigation2) | +| ROS2 Build Farm | [](http://build.ros2.org/job/Cdev__navigation2__ubuntu_bionic_amd64/) | +| Code Coverage | [](https://codecov.io/gh/ros-planning/navigation2) | -[](https://hub.docker.com/r/rosplanning/navigation2) DockerHub - -[](http://build.ros2.org/job/Cdev__navigation2__ubuntu_bionic_amd64/) ROS Build Farm - -[](https://codecov.io/gh/ros-planning/navigation2) # Overview The ROS 2 Navigation System is the control system that enables a robot to autonomously reach a goal state, such as a specific position and orientation relative to a specific map. Given a current pose, a map, and a goal, such as a destination pose, the navigation system generates a plan to reach the goal, and outputs commands to autonomously drive the robot, respecting any safety constraints and avoiding obstacles encountered along the way. @@ -18,6 +17,9 @@ The ROS 2 Navigation System is the control system that enables a robot to autono # Documentation For detailed instructions on how to install and run the examples, please visit our [documentation site](https://ros-planning.github.io/navigation2/). +# API Documentation +Run `doxygen` in the root of this repository. It will generate a `/doc/*` directory containing the documentation. Entrypoint in a browser is index.html. + # Contributing [Contributions are welcome!](doc/README.md#contributing). For more information, please review our [contribution guidelines](https://ros-planning.github.io/navigation2/contribute/contribute_guidelines.html). diff --git a/nav2_bringup/bringup/launch/nav2_bringup_launch.py b/nav2_bringup/bringup/launch/nav2_bringup_launch.py index 92c43e3d52f373218922a36ca8aa406fb0fa3d54..3701d0b974e3d1373e315f33f15651a987f84bd6 100644 --- a/nav2_bringup/bringup/launch/nav2_bringup_launch.py +++ b/nav2_bringup/bringup/launch/nav2_bringup_launch.py @@ -22,6 +22,7 @@ from launch.actions import (DeclareLaunchArgument, GroupAction, from launch.conditions import IfCondition from launch.launch_description_sources import PythonLaunchDescriptionSource from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node from launch_ros.actions import PushRosNamespace @@ -38,7 +39,6 @@ def generate_launch_description(): params_file = LaunchConfiguration('params_file') bt_xml_file = LaunchConfiguration('bt_xml_file') autostart = LaunchConfiguration('autostart') - use_remappings = LaunchConfiguration('use_remappings') stdout_linebuf_envvar = SetEnvironmentVariable( 'RCUTILS_CONSOLE_STDOUT_LINE_BUFFERED', '1') @@ -78,10 +78,6 @@ def generate_launch_description(): 'autostart', default_value='true', description='Automatically startup the nav2 stack') - declare_use_remappings_cmd = DeclareLaunchArgument( - 'use_remappings', default_value='false', - description='Arguments to pass to all nodes launched by the file') - # Specify the actions bringup_cmd_group = GroupAction([ PushRosNamespace( @@ -96,8 +92,7 @@ def generate_launch_description(): 'use_sim_time': use_sim_time, 'autostart': autostart, 'params_file': params_file, - 'use_lifecycle_mgr': 'false', - 'use_remappings': use_remappings}.items()), + 'use_lifecycle_mgr': 'false'}.items()), IncludeLaunchDescription( PythonLaunchDescriptionSource(os.path.join(launch_dir, 'nav2_navigation_launch.py')), @@ -107,7 +102,6 @@ def generate_launch_description(): 'params_file': params_file, 'bt_xml_file': bt_xml_file, 'use_lifecycle_mgr': 'false', - 'use_remappings': use_remappings, 'map_subscribe_transient_local': 'true'}.items()), ]) @@ -125,7 +119,6 @@ def generate_launch_description(): ld.add_action(declare_params_file_cmd) ld.add_action(declare_autostart_cmd) ld.add_action(declare_bt_xml_cmd) - ld.add_action(declare_use_remappings_cmd) # Add the actions to launch all of the navigation nodes ld.add_action(bringup_cmd_group) diff --git a/nav2_bringup/bringup/launch/nav2_localization_launch.py b/nav2_bringup/bringup/launch/nav2_localization_launch.py index bbf5e78b3306c49e5bff1a97426d8ac3a47b7008..04d5bba795197efb89e7f9cbb6ede1597c16c69e 100644 --- a/nav2_bringup/bringup/launch/nav2_localization_launch.py +++ b/nav2_bringup/bringup/launch/nav2_localization_launch.py @@ -20,8 +20,7 @@ from launch import LaunchDescription from launch.actions import DeclareLaunchArgument, SetEnvironmentVariable from launch.conditions import IfCondition from launch.substitutions import LaunchConfiguration - -from nav2_common.launch import Node +from launch_ros.actions import Node from nav2_common.launch import RewrittenYaml @@ -43,9 +42,7 @@ def generate_launch_description(): # https://github.com/ros/robot_state_publisher/pull/30 # TODO(orduno) Substitute with `PushNodeRemapping` # https://github.com/ros2/launch_ros/issues/56 - remappings = [((namespace, '/tf'), '/tf'), - ((namespace, '/tf_static'), '/tf_static'), - ('/tf', 'tf'), + remappings = [('/tf', 'tf'), ('/tf_static', 'tf_static')] # Create our own temporary YAML files that include substitutions @@ -95,7 +92,6 @@ def generate_launch_description(): node_name='map_server', output='screen', parameters=[configured_params], - use_remappings=IfCondition(use_remappings), remappings=remappings), Node( @@ -104,7 +100,6 @@ def generate_launch_description(): node_name='amcl', output='screen', parameters=[configured_params], - use_remappings=IfCondition(use_remappings), remappings=remappings), Node( diff --git a/nav2_bringup/bringup/launch/nav2_multi_tb3_simulation_launch.py b/nav2_bringup/bringup/launch/nav2_multi_tb3_simulation_launch.py index eb1ce88317f89844e3e70b634e85eda408928cd9..a95b29e963e65187e8d227736663f7ca14b76ee6 100644 --- a/nav2_bringup/bringup/launch/nav2_multi_tb3_simulation_launch.py +++ b/nav2_bringup/bringup/launch/nav2_multi_tb3_simulation_launch.py @@ -154,7 +154,6 @@ def generate_launch_description(): 'params_file': params_file, 'bt_xml_file': bt_xml_file, 'autostart': autostart, - 'use_remappings': 'True', 'use_rviz': 'False', 'use_simulator': 'False', 'headless': 'False', diff --git a/nav2_bringup/bringup/launch/nav2_navigation_launch.py b/nav2_bringup/bringup/launch/nav2_navigation_launch.py index 7f82d6619cfd84d3c9205f0beaec8a286a1a452a..8626cdcec8dfa37a6ffe39be0a165843f1cb01cc 100644 --- a/nav2_bringup/bringup/launch/nav2_navigation_launch.py +++ b/nav2_bringup/bringup/launch/nav2_navigation_launch.py @@ -20,8 +20,7 @@ from launch import LaunchDescription from launch.actions import DeclareLaunchArgument, SetEnvironmentVariable from launch.conditions import IfCondition from launch.substitutions import LaunchConfiguration - -from nav2_common.launch import Node +from launch_ros.actions import Node from nav2_common.launch import RewrittenYaml @@ -35,6 +34,7 @@ def generate_launch_description(): params_file = LaunchConfiguration('params_file') bt_xml_file = LaunchConfiguration('bt_xml_file') use_remappings = LaunchConfiguration('use_remappings') + map_subscribe_transient_local = LaunchConfiguration('map_subscribe_transient_local') lifecycle_nodes = ['controller_server', 'planner_server', @@ -48,9 +48,7 @@ def generate_launch_description(): # https://github.com/ros/robot_state_publisher/pull/30 # TODO(orduno) Substitute with `PushNodeRemapping` # https://github.com/ros2/launch_ros/issues/56 - remappings = [((namespace, '/tf'), '/tf'), - ((namespace, '/tf_static'), '/tf_static'), - ('/tf', 'tf'), + remappings = [('/tf', 'tf'), ('/tf_static', 'tf_static')] # Create our own temporary YAML files that include substitutions @@ -99,7 +97,7 @@ def generate_launch_description(): description='Arguments to pass to all nodes launched by the file'), DeclareLaunchArgument( - 'map_subscribe_transient_local', default_value='true', + 'map_subscribe_transient_local', default_value='false', description='Whether to set the map subscriber QoS to transient local'), Node( @@ -107,7 +105,6 @@ def generate_launch_description(): node_executable='controller_server', output='screen', parameters=[configured_params], - use_remappings=IfCondition(use_remappings), remappings=remappings), Node( @@ -116,7 +113,6 @@ def generate_launch_description(): node_name='planner_server', output='screen', parameters=[configured_params], - use_remappings=IfCondition(use_remappings), remappings=remappings), Node( @@ -125,7 +121,6 @@ def generate_launch_description(): node_name='recoveries_server', output='screen', parameters=[{'use_sim_time': use_sim_time}], - use_remappings=IfCondition(use_remappings), remappings=remappings), Node( @@ -134,7 +129,6 @@ def generate_launch_description(): node_name='bt_navigator', output='screen', parameters=[configured_params], - use_remappings=IfCondition(use_remappings), remappings=remappings), Node( @@ -143,7 +137,6 @@ def generate_launch_description(): node_name='waypoint_follower', output='screen', parameters=[configured_params], - use_remappings=IfCondition(use_remappings), remappings=remappings), Node( diff --git a/nav2_bringup/bringup/launch/nav2_rviz_launch.py b/nav2_bringup/bringup/launch/nav2_rviz_launch.py index fcae590a75a3060a1a881fee081331e437dfb7d7..67ab0c3ff2dc6afe0c4b7537219aad9a6ffc2b41 100644 --- a/nav2_bringup/bringup/launch/nav2_rviz_launch.py +++ b/nav2_bringup/bringup/launch/nav2_rviz_launch.py @@ -22,8 +22,8 @@ from launch.conditions import IfCondition, UnlessCondition from launch.event_handlers import OnProcessExit from launch.events import Shutdown from launch.substitutions import LaunchConfiguration - -from nav2_common.launch import Node, ReplaceString +from launch_ros.actions import Node +from nav2_common.launch import ReplaceString def generate_launch_description(): @@ -73,7 +73,6 @@ def generate_launch_description(): node_namespace=namespace, arguments=['-d', namespaced_rviz_config_file], output='screen', - use_remappings=IfCondition('True'), remappings=[('/tf', 'tf'), ('/tf_static', 'tf_static'), ('/goal_pose', 'goal_pose'), diff --git a/nav2_bringup/bringup/launch/nav2_tb3_simulation_launch.py b/nav2_bringup/bringup/launch/nav2_tb3_simulation_launch.py index dac6a576ccc461919abfa73611815d2f40036571..4bb78445d09f38a001a823a2d9ed23d8871eeedd 100644 --- a/nav2_bringup/bringup/launch/nav2_tb3_simulation_launch.py +++ b/nav2_bringup/bringup/launch/nav2_tb3_simulation_launch.py @@ -23,8 +23,7 @@ from launch.actions import DeclareLaunchArgument, ExecuteProcess, IncludeLaunchD from launch.conditions import IfCondition from launch.launch_description_sources import PythonLaunchDescriptionSource from launch.substitutions import LaunchConfiguration, PythonExpression - -from nav2_common.launch import Node +from launch_ros.actions import Node def generate_launch_description(): @@ -40,7 +39,6 @@ def generate_launch_description(): params_file = LaunchConfiguration('params_file') bt_xml_file = LaunchConfiguration('bt_xml_file') autostart = LaunchConfiguration('autostart') - use_remappings = LaunchConfiguration('use_remappings') # Launch configuration variables specific to simulation rviz_config_file = LaunchConfiguration('rviz_config_file') @@ -56,9 +54,7 @@ def generate_launch_description(): # https://github.com/ros/robot_state_publisher/pull/30 # TODO(orduno) Substitute with `PushNodeRemapping` # https://github.com/ros2/launch_ros/issues/56 - remappings = [((namespace, '/tf'), '/tf'), - ((namespace, '/tf_static'), '/tf_static'), - ('/tf', 'tf'), + remappings = [('/tf', 'tf'), ('/tf_static', 'tf_static')] # Declare the launch arguments @@ -98,10 +94,6 @@ def generate_launch_description(): 'autostart', default_value='true', description='Automatically startup the nav2 stack') - declare_use_remappings_cmd = DeclareLaunchArgument( - 'use_remappings', default_value='false', - description='Arguments to pass to all nodes launched by the file') - declare_rviz_config_file_cmd = DeclareLaunchArgument( 'rviz_config_file', default_value=os.path.join(bringup_dir, 'rviz', 'nav2_default_view.rviz'), @@ -157,7 +149,6 @@ def generate_launch_description(): node_namespace=namespace, output='screen', parameters=[{'use_sim_time': use_sim_time}], - use_remappings=IfCondition(use_remappings), remappings=remappings, arguments=[urdf]) @@ -189,7 +180,6 @@ def generate_launch_description(): ld.add_action(declare_params_file_cmd) ld.add_action(declare_bt_xml_cmd) ld.add_action(declare_autostart_cmd) - ld.add_action(declare_use_remappings_cmd) ld.add_action(declare_rviz_config_file_cmd) ld.add_action(declare_use_simulator_cmd) diff --git a/nav2_bringup/nav2_gazebo_spawner/nav2_gazebo_spawner/nav2_gazebo_spawner.py b/nav2_bringup/nav2_gazebo_spawner/nav2_gazebo_spawner/nav2_gazebo_spawner.py index bfe1897ebf11559ab4deb5605cc11812fdd8fedd..5f4de1d913f312534c29c9503de6d7cd532a4aed 100644 --- a/nav2_bringup/nav2_gazebo_spawner/nav2_gazebo_spawner/nav2_gazebo_spawner.py +++ b/nav2_bringup/nav2_gazebo_spawner/nav2_gazebo_spawner/nav2_gazebo_spawner.py @@ -83,7 +83,7 @@ def main(): break ros_params = plugin.find('ros') - ros_tf_remap = ET.SubElement(ros_params, 'argument') + ros_tf_remap = ET.SubElement(ros_params, 'remapping') ros_tf_remap.text = '/tf:=/' + args.robot_namespace + '/tf' # Set data for request diff --git a/nav2_common/nav2_common/launch/__init__.py b/nav2_common/nav2_common/launch/__init__.py index 82764712d088abc82d282abfb6b4af42a2a626d8..1f0638f81a02babb117be0d3ec58e19c50980d2f 100644 --- a/nav2_common/nav2_common/launch/__init__.py +++ b/nav2_common/nav2_common/launch/__init__.py @@ -14,4 +14,3 @@ from .rewritten_yaml import RewrittenYaml from .replace_string import ReplaceString -from .node import Node diff --git a/nav2_common/nav2_common/launch/node.py b/nav2_common/nav2_common/launch/node.py deleted file mode 100644 index b27c035e726a771be492f470d6e2535b50dc4445..0000000000000000000000000000000000000000 --- a/nav2_common/nav2_common/launch/node.py +++ /dev/null @@ -1,385 +0,0 @@ -# Copyright 2018 Open Source Robotics Foundation, Inc. -# Copyright (c) 2019 Intel Corporation -# -# 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. - -"""Module for the Node action.""" - -import os -import pathlib -from tempfile import NamedTemporaryFile -from typing import cast -from typing import Dict -from typing import Iterable -from typing import List -from typing import Optional -from typing import Text # noqa: F401 -from typing import Tuple # noqa: F401 -from typing import Union - -from launch import Condition -from launch.action import Action -from launch.actions import ExecuteProcess -from launch.frontend import Entity -# TODO(orduno) See comment below -# from launch.frontend import expose_action -from launch.frontend import Parser -from launch.launch_context import LaunchContext -import launch.logging -from launch.some_substitutions_type import SomeSubstitutionsType -from launch.substitutions import LocalSubstitution -from launch.substitutions import TextSubstitution -from launch.utilities import ensure_argument_type -from launch.utilities import normalize_to_list_of_substitutions -from launch.utilities import perform_substitutions - -from launch_ros.parameters_type import SomeParameters -from launch_ros.remap_rule_type import SomeRemapRules -from launch_ros.substitutions import ExecutableInPackage -from launch_ros.utilities import evaluate_parameters -from launch_ros.utilities import normalize_parameters -from launch_ros.utilities import normalize_remap_rules - -from rclpy.validate_namespace import validate_namespace -from rclpy.validate_node_name import validate_node_name - -import yaml - - -#TODO(orduno) Figure out how to import this decorator correctly -# @expose_action('node') -class Node(ExecuteProcess): - """Action that executes a ROS node.""" - - def __init__( - self, *, - package: SomeSubstitutionsType, - node_executable: SomeSubstitutionsType, - node_name: Optional[SomeSubstitutionsType] = None, - node_namespace: SomeSubstitutionsType = '', - parameters: Optional[SomeParameters] = None, - use_remappings: Optional[Condition] = None, - remappings: Optional[SomeRemapRules] = None, - arguments: Optional[Iterable[SomeSubstitutionsType]] = None, - **kwargs - ) -> None: - """ - Construct an Node action. - - Many arguments are passed eventually to - :class:`launch.actions.ExecuteProcess`, so see the documentation of - that class for additional details. - However, the `cmd` is not meant to be used, instead use the - `node_executable` and `arguments` keyword arguments to this function. - - This action, once executed, delegates most work to the - :class:`launch.actions.ExecuteProcess`, but it also converts some ROS - specific arguments into generic command line arguments. - - The launch_ros.substitutions.ExecutableInPackage substitution is used - to find the executable at runtime, so this Action also raise the - exceptions that substituion can raise when the package or executable - are not found. - - If the node_name is not given (or is None) then no name is passed to - the node on creation and instead the default name specified within the - code of the node is used instead. - - The node_namespace can either be absolute (i.e. starts with /) or - relative. - If absolute, then nothing else is considered and this is passed - directly to the node to set the namespace. - If relative, the namespace in the 'ros_namespace' LaunchConfiguration - will be prepended to the given relative node namespace. - If no node_namespace is given, then the default namespace `/` is - assumed. - - The parameters are passed as a list, with each element either a yaml - file that contains parameter rules (string or pathlib.Path to the full - path of the file), or a dictionary that specifies parameter rules. - Keys of the dictionary can be strings or an iterable of Substitutions - that will be expanded to a string. - Values in the dictionary can be strings, integers, floats, or tuples - of Substitutions that will be expanded to a string. - Additionally, values in the dictionary can be lists of the - aforementioned types, or another dictionary with the same properties. - A yaml file with the resulting parameters from the dictionary will be - written to a temporary file, the path to which will be passed to the - node. - Multiple dictionaries/files can be passed: each file path will be - passed in in order to the node (where the last definition of a - parameter takes effect). - - :param: package the package in which the node executable can be found - :param: node_executable the name of the executable to find - :param: node_name the name of the node - :param: node_namespace the ros namespace for this Node - :param: parameters list of names of yaml files with parameter rules, - or dictionaries of parameters. - :param: use_remappings whether to apply the remappings at runtime. - :param: remappings ordered list of 'to' and 'from' string pairs to be - passed to the node as ROS remapping rules - :param: arguments list of extra arguments for the node - """ - cmd = [ExecutableInPackage(package=package, executable=node_executable)] - cmd += [] if arguments is None else arguments - # Reserve space for ros specific arguments. - # The substitutions will get expanded when the action is executed. - cmd += ['--ros-args'] # Prepend ros specific arguments with --ros-args flag - if node_name is not None: - cmd += ['-r', LocalSubstitution( - "ros_specific_arguments['name']", description='node name')] - if parameters is not None: - ensure_argument_type(parameters, (list), 'parameters', 'Node') - # All elements in the list are paths to files with parameters (or substitutions that - # evaluate to paths), or dictionaries of parameters (fields can be substitutions). - i = 0 - for param in parameters: - cmd += ['--params-file', LocalSubstitution( - "ros_specific_arguments['params'][{}]".format(i), - description='parameter {}'.format(i))] - i += 1 - normalized_params = normalize_parameters(parameters) - if remappings is not None: - i = 0 - for remapping in normalize_remap_rules(remappings): - k, v = remapping - # TODO(orduno) For some reason the remaps space should be reserved. - # If not reserved and cmd is extended (with remap args) - # on `execute`, the remaps are not applied, even when the - # command passed does include remap args - # e.g. --ros-args -r /tf:=tf - # For that reason we reserve the space here and together - # with the remap flag ('-r') - cmd += [LocalSubstitution("remap_flag"), LocalSubstitution( - "ros_specific_arguments['remaps'][{}]".format(i), - description='remapping {}'.format(i))] - i += 1 - super().__init__(cmd=cmd, **kwargs) - self.__package = package - self.__node_executable = node_executable - self.__node_name = node_name - self.__node_namespace = node_namespace - self.__parameters = [] if parameters is None else normalized_params - self.__use_remappings = use_remappings - self.__remappings = [] if remappings is None else remappings - self.__arguments = arguments - - self.__expanded_node_name = '<node_name_unspecified>' - self.__expanded_node_namespace = '' - self.__final_node_name = None # type: Optional[Text] - self.__expanded_parameter_files = None # type: Optional[List[Text]] - self.__expanded_remappings = None # type: Optional[List[Tuple[Text, Text]]] - - self.__substitutions_performed = False - - self.__logger = launch.logging.get_logger(__name__) - - @staticmethod - def parse_nested_parameters(params, parser): - """Normalize parameters as expected by Node constructor argument.""" - def get_nested_dictionary_from_nested_key_value_pairs(params): - """Convert nested params in a nested dictionary.""" - param_dict = {} - for param in params: - name = tuple(parser.parse_substitution(param.get_attr('name'))) - value = param.get_attr('value', data_type=None, optional=True) - nested_params = param.get_attr('param', data_type=List[Entity], optional=True) - if value is not None and nested_params: - raise RuntimeError('param and value attributes are mutually exclusive') - elif value is not None: - def normalize_scalar_value(value): - if isinstance(value, str): - value = parser.parse_substitution(value) - if len(value) == 1 and isinstance(value[0], TextSubstitution): - value = value[0].text # python `str` are not converted like yaml - return value - if isinstance(value, list): - value = [normalize_scalar_value(x) for x in value] - else: - value = normalize_scalar_value(value) - param_dict[name] = value - elif nested_params: - param_dict.update({ - name: get_nested_dictionary_from_nested_key_value_pairs(nested_params) - }) - else: - raise RuntimeError('either a value attribute or nested params are needed') - return param_dict - - normalized_params = [] - params_without_from = [] - for param in params: - from_attr = param.get_attr('from', optional=True) - name = param.get_attr('name', optional=True) - if from_attr is not None and name is not None: - raise RuntimeError('name and from attributes are mutually exclusive') - elif from_attr is not None: - # 'from' attribute ignores 'name' attribute, - # it's not accepted to be nested, - # and it can not have children. - normalized_params.append(parser.parse_substitution(from_attr)) - continue - elif name is not None: - params_without_from.append(param) - continue - raise ValueError('param Entity should have name or from attribute') - normalized_params.append( - get_nested_dictionary_from_nested_key_value_pairs(params_without_from)) - return normalized_params - - @classmethod - def parse(cls, entity: Entity, parser: Parser): - """Parse node.""" - # See parse method of `ExecuteProcess` - _, kwargs = super().parse(entity, parser, 'args') - kwargs['arguments'] = kwargs['args'] - del kwargs['args'] - kwargs['node_name'] = kwargs['name'] - del kwargs['name'] - kwargs['package'] = parser.parse_substitution(entity.get_attr('pkg')) - kwargs['node_executable'] = parser.parse_substitution(entity.get_attr('exec')) - ns = entity.get_attr('namespace', optional=True) - if ns is not None: - kwargs['node_namespace'] = parser.parse_substitution(ns) - remappings = entity.get_attr('remap', optional=True) - if remappings is not None: - kwargs['remappings'] = [ - ( - parser.parse_substitution(remap.get_attr('from')), - parser.parse_substitution(remap.get_attr('to')) - ) for remap in remappings - ] - parameters = entity.get_attr('param', data_type=List[Entity], optional=True) - if parameters is not None: - kwargs['parameters'] = cls.parse_nested_parameters(parameters, parser) - return cls, kwargs - - @property - def node_name(self): - """Getter for node_name.""" - if self.__final_node_name is None: - raise RuntimeError("cannot access 'node_name' before executing action") - return self.__final_node_name - - def _create_params_file_from_dict(self, params): - with NamedTemporaryFile(mode='w', prefix='launch_params_', delete=False) as h: - param_file_path = h.name - # TODO(dhood): clean up generated parameter files. - param_dict = {'/**': {'ros__parameters': params}} - yaml.dump(param_dict, h, default_flow_style=False) - return param_file_path - - def _perform_substitutions(self, context: LaunchContext) -> None: - try: - if self.__substitutions_performed: - # This function may have already been called by a subclass' `execute`, for example. - return - self.__substitutions_performed = True - if self.__node_name is not None: - self.__expanded_node_name = perform_substitutions( - context, normalize_to_list_of_substitutions(self.__node_name)) - validate_node_name(self.__expanded_node_name) - self.__expanded_node_name.lstrip('/') - self.__expanded_node_namespace = perform_substitutions( - context, normalize_to_list_of_substitutions(self.__node_namespace)) - if not self.__expanded_node_namespace.startswith('/'): - base_ns = context.launch_configurations.get('ros_namespace', '') - self.__expanded_node_namespace = ( - base_ns + '/' + self.__expanded_node_namespace - ).rstrip('/') - if ( - self.__expanded_node_namespace != '' and not - self.__expanded_node_namespace.startswith('/') - ): - self.__expanded_node_namespace = '/' + self.__expanded_node_namespace - if self.__expanded_node_namespace != '': - cmd_extension = ['-r', LocalSubstitution("ros_specific_arguments['ns']")] - self.cmd.extend([normalize_to_list_of_substitutions(x) for x in cmd_extension]) - validate_namespace(self.__expanded_node_namespace) - except Exception: - self.__logger.error( - "Error while expanding or validating node name or namespace for '{}':" - .format('package={}, node_executable={}, name={}, namespace={}'.format( - self.__package, - self.__node_executable, - self.__node_name, - self.__node_namespace, - )) - ) - raise - self.__final_node_name = '' - if self.__expanded_node_namespace not in ['', '/']: - self.__final_node_name += self.__expanded_node_namespace - self.__final_node_name += '/' + self.__expanded_node_name - # expand parameters too - if self.__parameters is not None: - self.__expanded_parameter_files = [] - evaluated_parameters = evaluate_parameters(context, self.__parameters) - for params in evaluated_parameters: - if isinstance(params, dict): - param_file_path = self._create_params_file_from_dict(params) - elif isinstance(params, pathlib.Path): - param_file_path = str(params) - else: - raise RuntimeError('invalid normalized parameters {}'.format(repr(params))) - if not os.path.isfile(param_file_path): - self.__logger.warning( - 'Parameter file path is not a file: {}'.format(param_file_path), - ) - # Don't skip adding the file to the parameter list since space has been - # reserved for it in the ros_specific_arguments. - self.__expanded_parameter_files.append(param_file_path) - # expand remappings too - if self.__remappings is not None: - self.__expanded_remappings = [] - for k, v in self.__remappings: - key = perform_substitutions(context, normalize_to_list_of_substitutions(k)) - value = perform_substitutions(context, normalize_to_list_of_substitutions(v)) - self.__expanded_remappings.append((key, value)) - - def execute(self, context: LaunchContext) -> Optional[List[Action]]: - """ - Execute the action. - - Delegated to :meth:`launch.actions.ExecuteProcess.execute`. - """ - self._perform_substitutions(context) - # Prepare the ros_specific_arguments list and add it to the context so that the - # LocalSubstitution placeholders added to the the cmd can be expanded using the contents. - ros_specific_arguments: Dict[str, Union[str, List[str]]] = {} - if self.__node_name is not None: - ros_specific_arguments['name'] = '__node:={}'.format(self.__expanded_node_name) - if self.__expanded_node_namespace != '': - ros_specific_arguments['ns'] = '__ns:={}'.format(self.__expanded_node_namespace) - if self.__expanded_parameter_files is not None: - ros_specific_arguments['params'] = self.__expanded_parameter_files - if self.__expanded_remappings is not None: - ros_specific_arguments['remaps'] = [] - for remapping_from, remapping_to in self.__expanded_remappings: - remap_arguments = cast(List[str], ros_specific_arguments['remaps']) - if self.__use_remappings is None or self.__use_remappings.evaluate(context): - remap_arguments.append('{}:={}'.format(remapping_from, remapping_to)) - else: - remap_arguments.append('') - if self.__use_remappings is None or self.__use_remappings.evaluate(context): - context.extend_locals({'remap_flag': '-r'}) - else: - context.extend_locals({'remap_flag': ''}) - context.extend_locals({'ros_specific_arguments': ros_specific_arguments}) - return super().execute(context) - - @property - def expanded_node_namespace(self): - """Getter for expanded_node_namespace.""" - return self.__expanded_node_namespace diff --git a/nav2_controller/src/progress_checker.cpp b/nav2_controller/src/progress_checker.cpp index 21efd514c1624de1064d8f42bc4e7f7604ea719c..7f4df3bbda2e26f14398692fed2adc93b7dd4add 100644 --- a/nav2_controller/src/progress_checker.cpp +++ b/nav2_controller/src/progress_checker.cpp @@ -29,7 +29,7 @@ ProgressChecker::ProgressChecker(const rclcpp::Node::SharedPtr & node) // Scale is set to 0 by default, so if it was not set otherwise, set to 0 nh_->get_parameter_or("required_movement_radius", radius_, 0.5); double time_allowance_param; - nh_->get_parameter_or("movement_time_allowance_", time_allowance_param, 10.0); + nh_->get_parameter_or("movement_time_allowance", time_allowance_param, 10.0); time_allowance_ = rclcpp::Duration::from_seconds(time_allowance_param); } diff --git a/nav2_costmap_2d/CMakeLists.txt b/nav2_costmap_2d/CMakeLists.txt index 483e74aa4bd534fb8cb3f6427435db94e87dff22..abd70ac4619d1edcede0fc7e700e0454d6eb75f3 100644 --- a/nav2_costmap_2d/CMakeLists.txt +++ b/nav2_costmap_2d/CMakeLists.txt @@ -142,7 +142,7 @@ install(TARGETS ) install(FILES costmap_plugins.xml - DESTINATION share + DESTINATION share/${PROJECT_NAME} ) install(DIRECTORY include/ diff --git a/nav2_dwb_controller/dwb_critics/CMakeLists.txt b/nav2_dwb_controller/dwb_critics/CMakeLists.txt index 7ddcde2dde70d30e7342c9cef0f498ef8c00cffa..b892eb7d2898b646e0174e0942524ac05a0f9548 100644 --- a/nav2_dwb_controller/dwb_critics/CMakeLists.txt +++ b/nav2_dwb_controller/dwb_critics/CMakeLists.txt @@ -66,7 +66,7 @@ install(DIRECTORY include/ DESTINATION include/ ) install(FILES default_critics.xml - DESTINATION share + DESTINATION share/${PROJECT_NAME} ) if(BUILD_TESTING) diff --git a/nav2_dwb_controller/dwb_plugins/CMakeLists.txt b/nav2_dwb_controller/dwb_plugins/CMakeLists.txt index 9645f9ce1225d7fab715c798294df552fc8157fa..64348944b5f170a11a73040cb3df1682930fb3b8 100644 --- a/nav2_dwb_controller/dwb_plugins/CMakeLists.txt +++ b/nav2_dwb_controller/dwb_plugins/CMakeLists.txt @@ -69,7 +69,7 @@ install(DIRECTORY include/ DESTINATION include/ ) install(FILES plugins.xml - DESTINATION share + DESTINATION share/${PROJECT_NAME} ) ament_export_include_directories(include) diff --git a/nav2_lifecycle_manager/include/nav2_lifecycle_manager/lifecycle_manager.hpp b/nav2_lifecycle_manager/include/nav2_lifecycle_manager/lifecycle_manager.hpp index c86758938e4f56404e2da3fb462587245305ec4e..384f33e01820b4915516dd23b8f51ae554a9f279 100644 --- a/nav2_lifecycle_manager/include/nav2_lifecycle_manager/lifecycle_manager.hpp +++ b/nav2_lifecycle_manager/include/nav2_lifecycle_manager/lifecycle_manager.hpp @@ -129,7 +129,7 @@ protected: /** * @brief For each node in the map, transition to the new target state */ - bool changeStateForAllNodes(std::uint8_t transition, bool reverse_order = false); + bool changeStateForAllNodes(std::uint8_t transition); // Convenience function to highlight the output on the console /** diff --git a/nav2_lifecycle_manager/src/lifecycle_manager.cpp b/nav2_lifecycle_manager/src/lifecycle_manager.cpp index 88854011b5c199f775433c2e6e7b35ce6e802a1f..fbe433445b911854e8ddec066197381f7d63e2af 100644 --- a/nav2_lifecycle_manager/src/lifecycle_manager.cpp +++ b/nav2_lifecycle_manager/src/lifecycle_manager.cpp @@ -148,9 +148,11 @@ LifecycleManager::changeStateForNode(const std::string & node_name, std::uint8_t } bool -LifecycleManager::changeStateForAllNodes(std::uint8_t transition, bool reverse_order) +LifecycleManager::changeStateForAllNodes(std::uint8_t transition) { - if (!reverse_order) { + if (transition == Transition::TRANSITION_CONFIGURE || + transition == Transition::TRANSITION_ACTIVATE) + { for (auto & node_name : node_names_) { if (!changeStateForNode(node_name, transition)) { return false; @@ -164,7 +166,6 @@ LifecycleManager::changeStateForAllNodes(std::uint8_t transition, bool reverse_o } } } - return true; } @@ -172,9 +173,9 @@ void LifecycleManager::shutdownAllNodes() { message("Deactivate, cleanup, and shutdown nodes"); - changeStateForAllNodes(Transition::TRANSITION_DEACTIVATE, true); - changeStateForAllNodes(Transition::TRANSITION_CLEANUP, true); - changeStateForAllNodes(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN, true); + changeStateForAllNodes(Transition::TRANSITION_DEACTIVATE); + changeStateForAllNodes(Transition::TRANSITION_CLEANUP); + changeStateForAllNodes(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN); } bool @@ -208,8 +209,8 @@ LifecycleManager::reset() { message("Resetting managed nodes..."); // Should transition in reverse order - if (!changeStateForAllNodes(Transition::TRANSITION_DEACTIVATE, true) || - !changeStateForAllNodes(Transition::TRANSITION_CLEANUP, true)) + if (!changeStateForAllNodes(Transition::TRANSITION_DEACTIVATE) || + !changeStateForAllNodes(Transition::TRANSITION_CLEANUP)) { RCLCPP_ERROR(get_logger(), "Failed to reset nodes: aborting reset"); return false; diff --git a/nav2_navfn_planner/CMakeLists.txt b/nav2_navfn_planner/CMakeLists.txt index 34fc36f2fb61d203c1c5a9db9bb34ab0fb05fe63..1315b65ed5ada9c2ab0e14561507962db5613c13 100644 --- a/nav2_navfn_planner/CMakeLists.txt +++ b/nav2_navfn_planner/CMakeLists.txt @@ -68,7 +68,7 @@ install(DIRECTORY include/ ) install(FILES global_planner_plugin.xml - DESTINATION share + DESTINATION share/${PROJECT_NAME} ) if(BUILD_TESTING) diff --git a/nav2_recoveries/CMakeLists.txt b/nav2_recoveries/CMakeLists.txt index 0209845d8fa707f75a5765118b8c8a1b7b7d7d1d..6b0def011ed5e5ab635f262c6a2a9d7048d8c962 100644 --- a/nav2_recoveries/CMakeLists.txt +++ b/nav2_recoveries/CMakeLists.txt @@ -118,7 +118,7 @@ install(DIRECTORY include/ ) install(FILES recovery_plugin.xml - DESTINATION share + DESTINATION share/${PROJECT_NAME} ) if(BUILD_TESTING) diff --git a/nav2_system_tests/README.md b/nav2_system_tests/README.md index f9ba8672db94939174b92225a3a6659705310ed4..c210085882177732bc90bc2abbaf8ae9784371e4 100644 --- a/nav2_system_tests/README.md +++ b/nav2_system_tests/README.md @@ -29,5 +29,8 @@ Test the integration of several components and subsystems. - Command chain (Mission Planning, Mission Execution, Navigation System, Robot Interface) ## 3. System Testing +Test the lifecycle startup and shutdown of nodes. + - [Updown Test](src/updown/README.md) + Test the integration of all subsystems. - [System Test](src/system/README.md) diff --git a/nav2_system_tests/src/updown/README.md b/nav2_system_tests/src/updown/README.md new file mode 100644 index 0000000000000000000000000000000000000000..abfbf0a900627775c214bc08fe16d406b397dd8e --- /dev/null +++ b/nav2_system_tests/src/updown/README.md @@ -0,0 +1,22 @@ +# Navigation2 Updown Test + +This is a 'top level' system test which tests the lifecycle bringup and shutdown of the system. + +## To run the test +``` +ros2 launch nav2_system_tests test_updown_launch.py +``` + +If the test passes, you should see this comment in the output: +``` +[test_updown-13] [INFO] [test_updown]: **************************************************** TEST PASSED! +``` + +To run the test in a loop 1000x, run the `test_updown_reliablity` script and log the output: +``` +./test_updown_reliablity |& tee /tmp/updown.log +``` +When the test is completed, pipe the log to the `updownresults.py` script to get a summary of the results: +``` +./updownresults.py < /tmp/updown.log` +``` diff --git a/sphinx_doc/getting_started/index.rst b/sphinx_doc/getting_started/index.rst index 3b430fc0adf15444487ecdc98e6ff512a42b3d27..bd1c24dd5aa52d79395a01227d74088c02d77009 100644 --- a/sphinx_doc/getting_started/index.rst +++ b/sphinx_doc/getting_started/index.rst @@ -54,7 +54,7 @@ Running the Example .. code-block:: bash - ros2 launch nav2_bringup nav2_tb3_simulation_launch.py + ros2 launch nav2_bringup nav2_simulation_launch.py If everything has started correctly, you will see the RViz and Gazebo GUIs like diff --git a/sphinx_doc/howtos/build_instructions/build_docs/build_troubleshooting_guide.rst b/sphinx_doc/howtos/build_instructions/build_docs/build_troubleshooting_guide.rst new file mode 100644 index 0000000000000000000000000000000000000000..9d1a46e862e6d261f55ec5e4e5769741f2a332a6 --- /dev/null +++ b/sphinx_doc/howtos/build_instructions/build_docs/build_troubleshooting_guide.rst @@ -0,0 +1,31 @@ +.. _build-troubleshooting-guide: + +Build Troubleshooting Guide +********************************************** + +Common Navigation2 Dependencies Build Failures +============================================== + +* Makse sure that .bashrc file has no ROS environment variables in it. Open new terminals and try to build the packages again. + +* Make sure to run rosdep for the correct ROS 2 distribution. + ``rosdep install -y -r -q --from-paths src --ignore-src --rosdistro <ros2-distro>`` + +* Make sure that the ``setup.bash`` is sourced in the ROS 2 installation or ROS 2 build workspace. Check if you can run talker and listener nodes. + +* Make sure that the ``setup.bash`` in ``nav2_depend_ws/install`` is sourced. + +* Check if you have the correct ROS version and distribution. ``printenv | grep -i ROS`` + +* Make sure to run rosdep for the correct ROS 2 distribution. + + ``rosdep install -y -r -q --from-paths src --ignore-src --rosdistro <ros2-distro>`` + +* Search `GitHub Issues <https://github.com/ros-planning/navigation2/issues>`_ + +Still can't solve it? Let us know about your issue. `Open a ticket <https://github.com/ros-planning/navigation2/issues/new>`_. + +Reporting Issue +=============== + +- If you run into any issues when building Navigation2, you can use the search tool in the issues tab on `GitHub <https://github.com/ros-planning/navigation2/issues>`_ and always feel free to `open a ticket <https://github.com/ros-planning/navigation2/issues/new>`_. diff --git a/sphinx_doc/howtos/build_instructions/build_docs/manual_build/master_build.rst b/sphinx_doc/howtos/build_instructions/build_docs/manual_build/master_build.rst new file mode 100644 index 0000000000000000000000000000000000000000..8d7463a6614cbc21d12d47bbe9657451d85f666e --- /dev/null +++ b/sphinx_doc/howtos/build_instructions/build_docs/manual_build/master_build.rst @@ -0,0 +1,43 @@ +.. _master-build: + +Build Navigation2 Master Branch +******************************* + +The instructions to build Navigation2 Master branch from source. + +Step 1- Build ROS 2 +------------------- + +* `ROS2 Build Instructions <https://index.ros.org/doc/ros2/Installation>`_ +* When building ROS 2 from source, make sure that the `ros2.repos` file is from the `master` branch. + +Step 2- Build Navigation2 Dependencies +-------------------------------------- + +- Source the setup.bash file in the ROS 2 build workspace. + + ``source ~/ros2_ws/install/setup.bash`` + +**Build and install Navigation2 dependencies:** + +.. code:: bash + + mkdir -p ~/nav2_depend_ws/src + cd ~/nav2_depend_ws + wget https://raw.githubusercontent.com/ros-planning/navigation2/master/tools/ros2_dependencies.repos + vcs import src < ros2_dependencies.repos + rosdep install -y -r -q --from-paths src --ignore-src --rosdistro eloquent + colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release + +Step 3- Build Navigation2 +------------------------- + +.. code:: bash + + source ~/nav2_depend_ws/install/setup.bash + mkdir -p ~/navigation2_ws/src + cd ~/navigation2_ws/src + git clone https://github.com/ros-planning/navigation2.git --branch master + cd ~/navigation2_ws + rosdep install -y -r -q --from-paths src --ignore-src --rosdistro eloquent + colcon build --symlink-install diff --git a/sphinx_doc/howtos/build_instructions/build_docs/manual_build/specific_distro_build.rst b/sphinx_doc/howtos/build_instructions/build_docs/manual_build/specific_distro_build.rst new file mode 100644 index 0000000000000000000000000000000000000000..d50d253c5328ebe2ee90d06e04b7d402cc09db31 --- /dev/null +++ b/sphinx_doc/howtos/build_instructions/build_docs/manual_build/specific_distro_build.rst @@ -0,0 +1,47 @@ +.. _specific-distro-build: + +Build Navigation2 for a Specific Distribution +============================================= + +Step 1- Build ROS 2 +------------------- + +* `ROS2 Build Instructions <https://index.ros.org/doc/ros2/Installation>`_ +* Make sure that the `ros2.repos` file is from the ROS 2 distribution branch that you want to build. (e.g `eloquent-devel`) +* When installing the ROS 2 dependencies using rosdep, make sure to set `--rosdistro` to the desired ROS 2 distribution (e.g `eloquent`) +* The following build instructions are for ROS2 Eloquent. You can change eloquent to your target ROS2 distrubution. + +Step 2- Build Navigation2 Dependencies +-------------------------------------- + +- Source the setup.bash file in the ROS 2 build workspace. + + ``source ~/ros2_ws/install/setup.bash`` + +**Build and install Navigation2 dependencies:** + +.. code:: bash + + mkdir -p ~/nav2_depend_ws/src + cd ~/nav2_depend_ws + wget https://raw.githubusercontent.com/ros-planning/navigation2/eloquent-devel/tools/ros2_dependencies.repos + vcs import src < ros2_dependencies.repos + rosdep install -y -r -q --from-paths src --ignore-src --rosdistro eloquent + colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release + + +Step 3- Build Navigation2 +------------------------- + +- To build Navigation2 stack for a specific ROS 2 distribution such as Crystal or Dashing, set ``--branch`` to the selected branch name. (e.g- ``eloquent-devel``) +- Also you need to change ``--rosdistro`` to the selected ROS 2 distribution name. (e.g ``eloquent``) + +.. code:: bash + + source ~/nav2_depend_ws/install/setup.bash + mkdir -p ~/navigation2_ws/src + cd ~/navigation2_ws/src + git clone https://github.com/ros-planning/navigation2.git --branch eloquent-devel + cd ~/navigation2_ws + rosdep install -y -r -q --from-paths src --ignore-src --rosdistro eloquent + colcon build --symlink-install diff --git a/sphinx_doc/howtos/build_instructions/build_docs/quick_start.rst b/sphinx_doc/howtos/build_instructions/build_docs/quick_start.rst new file mode 100644 index 0000000000000000000000000000000000000000..e7bd11b6c24c22316566a9d42cf66712c5f4b01b --- /dev/null +++ b/sphinx_doc/howtos/build_instructions/build_docs/quick_start.rst @@ -0,0 +1,39 @@ +.. _quick-start: + +Quickstart Using the Initial Setup Script +***************************************** + +Steps +===== + + - Install all ROS 2 dependencies from the `ROS2 Installation page <https://index.ros.org/doc/ros2/Installation/Dashing/Linux-Development-Setup>`_ + + - Ensure there are no ROS environment variables set in your terminal or `.bashrc` file before taking the steps below.* + + +.. code:: bash + + mkdir <directory_for_workspaces> + cd <directory_for_workspaces> + wget https://raw.githubusercontent.com/ros-planning/navigation2/master/tools/initial_ros_setup.sh + chmod a+x initial_ros_setup.sh + ./initial_ros_setup.sh + + +**Summary of what's being done** + +The ``initial_ros_setup.sh`` script downloads four ROS workspaces and then builds them in the correct order. The four workspaces are: + +- **ROS 2 release**: This is the latest ROS 2 release as defined by the repos file found `here <https://github.com/ros2/ros2>`_ +- **ROS 2 dependencies**: This is a set of ROS 2 packages that aren't included in the ROS 2 release yet. However, you need them to be able to build Navigation2. This also includes packages that are part of the ROS 2 release where Navigation2 uses a different version. +- **Navigation2**: This repository. + +After all the workspaces are downloaded, run the `navigation2/tools/build_all.sh` script. `build_all.sh` builds each repo in the order listed above using the `colcon build --symlink-install` command. + +Options +======= + +The `initial_ros_setup.sh` accepts the following options: + +- `--no-ros2` This skips downloading and building the ROS 2 release. Instead it uses the binary packages and ``setup.sh`` installed in ``/opt/ros/<ros2-distro>`` +- ``--download-only`` This skips the build steps diff --git a/sphinx_doc/howtos/build_instructions/build_docs/use_case_recommendations.rst b/sphinx_doc/howtos/build_instructions/build_docs/use_case_recommendations.rst new file mode 100644 index 0000000000000000000000000000000000000000..ac25bb6ec04a522e41beaef72330ceb1aed07a1a --- /dev/null +++ b/sphinx_doc/howtos/build_instructions/build_docs/use_case_recommendations.rst @@ -0,0 +1,54 @@ +.. _use-case-recommendations: + +Use Case Recommendations +************************ + +Developer +--------- + +For developers, running the `initial_ros_setup.sh` once makes sense. After that, you'll typically want to maintain each repo manually using git. + +Most work will be done in the Navigation2 workspace, so just building that will save time. + +To build Navigation2 only, + +.. code:: bash + + cd <directory_for_workspaces>/navigation2_ws + source ../nav2_dependencies_ws/install/setup.sh + colcon build --symlink-install + + +In the case that the developer wants to change any dependencies, they can run +`<directory_for_workspaces>/navigation2_ws/src/navigation2/tools/build_all.sh` in a clean environment to get everything rebuilt easily + +Debugging +--------- + +To build Navigation2 with build symbols, use colcon build with the following flags and cmake arguments. + +.. code:: bash + + source ../nav2_dependencies_ws/install/setup.sh + cd <directory_for_workspaces>/navigation2_ws + colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Debug + + +This especially is helpful when debugging an issue with a debugger such as GDB and QtCreator. + +Build System +------------ + +An automated build system could make a clean directory and run the ``initial_ros_setup.sh`` script each time, however, that will generate a lot of unnecessary load on the upstream repo servers, and result in very long builds. + +Instead, it would be better to do an initial download of all the source and dependencies +``./initial_ros_setup.sh --download-only`` + +Then the CI tool can monitor the Navigation2 repo, update it as necessary, and rebuild using either the ``<directory_for_workspaces>/navigation2_ws/src/navigation2/tools/build_all.sh`` script or by running + +.. code:: bash + + cd <directory_for_workspaces>/navigation2_ws/src/navigation2 + source ../ros2_nav_dependencies_ws/install/setup.sh + colcon build --symlink-install + diff --git a/sphinx_doc/howtos/build_instructions/index.rst b/sphinx_doc/howtos/build_instructions/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..373dc0c8a4cb7119d536d9c0616454dad2ebe0da --- /dev/null +++ b/sphinx_doc/howtos/build_instructions/index.rst @@ -0,0 +1,40 @@ +.. _build-instructions: + +Build Instructions +################## + +The instructions to build **Navigation2 Stack** and **Navigation2 Dependencies**. + +**Build Options** + +There are two different recommended methods for building Navigation2 stack from source. + +1- Manually Build From Source : Manual step by step method to build Navigation2 + - :ref:`master-build` + - :ref:`specific-distro-build` + +2- Quickstart Using Initial Setup Script : An automated method to build Navigation2 in a simple and easy way. + - :ref:`quick-start` + +!!!! + +**Recommended Platform** + +* `Ubuntu 18.04 <http://releases.ubuntu.com/18.04/ubuntu-18.04.3-desktop-amd64.iso>`_ + +!!!! + +:ref:`use-case-recommendations` + +!!!! + +:ref:`build-troubleshooting-guide` + +.. toctree:: + :hidden: + + build_docs/manual_build/master_build.rst + build_docs/manual_build/specific_distro_build.rst + build_docs/quick_start.rst + build_docs/use_case_recommendations + build_docs/build_troubleshooting_guide.rst diff --git a/sphinx_doc/howtos/configuration/configuring-the-controller.rst b/sphinx_doc/howtos/configuration/configuring-the-controller.rst new file mode 100644 index 0000000000000000000000000000000000000000..6309b2a0a49485ad194790de1c217ce010b53ccf --- /dev/null +++ b/sphinx_doc/howtos/configuration/configuring-the-controller.rst @@ -0,0 +1,329 @@ +.. _configuring_the_controller: + +Configuring The Controller +########################## + +Controller Server +================= + +The controller server responds to FollowPath action requests. It runs a loop +that continuously computes new command velocities until the goal is reached, +cancelled or an error occurs. It computes command velocities by using the +services of a controller plugin. The parameters in this section are set on the +controller_server node + +Parameters +********** + +:controller_frequency: + +----------------+----------------------------------------------------------------------------+ + |**type** | double | + +----------------+----------------------------------------------------------------------------+ + |**default** | 20.0 | + +----------------+----------------------------------------------------------------------------+ + |**units** | Hz | + +----------------+----------------------------------------------------------------------------+ + |**description** | This parameter controls how often a new command velocity is | + | | published. It also controls how often the controller checks if the goal is| + | | reached. Faster robots may need to increase this value. Slower robots can | + | | use a lower value. | + +----------------+----------------------------------------------------------------------------+ + +:controller_plugin_ids: + +----------------+----------------------------------------------------------------------------+ + |**type** | vector<string> | + +----------------+----------------------------------------------------------------------------+ + |**default** | "FollowPath" | + +----------------+----------------------------------------------------------------------------+ + |**description** | The name of each controller plugin to be loaded into the controller server.| + | | Multiple controller plugins can be loaded simultaneously so they can share | + | | a costmap instance. The name assigned to the plugin using this parameter | + | | determines how it should be addressed in the *controller_id* field of the | + | | FollowPath action request. | + +----------------+----------------------------------------------------------------------------+ + + +:controller_plugin_types: + +----------------+----------------------------------------------------------------------------+ + |**type** | vector<string> | + +----------------+----------------------------------------------------------------------------+ + |**default** | "dwb_core::DWBLocalPlanner" | + +----------------+----------------------------------------------------------------------------+ + |**description** | The data type of each controller plugin to be loaded into the controller | + | | server. This is used by pluginlib to dyanmically load the object. This | + | | needs to be a class derived from nav2_core::LocalPlanner. The default | + | | controller is an instance of DWB whose parameters are here | + | | `DWB Controller`_ | + +----------------+----------------------------------------------------------------------------+ + +Progress Checker +================= + +This is a component of the controller server that verifies that the robot has moved sufficiently. +If the robot fails to make progress, the controller fails and triggers recoveries in the +behavior tree. The parameters in this section are set on the controller_server node. + +Parameters +********** + +:required_movement_radius: + +----------------+----------------------------------------------------------------------------+ + |**type** | double | + +----------------+----------------------------------------------------------------------------+ + |**default** | 0.5 | + +----------------+----------------------------------------------------------------------------+ + |**units** | m | + +----------------+----------------------------------------------------------------------------+ + |**description** | The absolute distance the robot must move from the previous checkpoint. If | + | | the robot doesn't move this far in *movement_time_allowance* seconds, an | + | | error is thrown. Once the robot moves this distance the time is reset | + +----------------+----------------------------------------------------------------------------+ + +:movement_time_allowance: + +----------------+----------------------------------------------------------------------------+ + |**type** | double | + +----------------+----------------------------------------------------------------------------+ + |**default** | 10.0 | + +----------------+----------------------------------------------------------------------------+ + |**units** | s | + +----------------+----------------------------------------------------------------------------+ + |**description** | Controls how much time the robot has time to show progress. If the robot | + | | fails to move more than *required_movement_radius* meters in this time, an | + | | error is thrown. For slow robots, this time should be extended. Reducing | + | | this time will cause the robot to recover more quickly if it is stuck, | + | | but too little time doesn't give the robot enough time to manoeuver in | + | | dyanamic enviroments | + +----------------+----------------------------------------------------------------------------+ + +DWB Controller +============== + +The DWB controller is the default controller in |PN|. It is a fork of `David Lu's +controller <https://github.com/locusrobotics/robot_navigation/tree/master/dwb_local_planner>`_ +modified for ROS 2. + +.. warning:: + + The parameters below are not properly scoped. The exact parameter names are + likely to change in the near future + +Parameters +********** + +:trajectory_generator_name: + +----------------+----------------------------------------------------------------------------+ + |**type** | string | + +----------------+----------------------------------------------------------------------------+ + |**default** | "dwb_plugins::StandardTrajectoryGenerator" | + +----------------+----------------------------------------------------------------------------+ + |**description** | This is the name of the pluginlib class to use as the trajectory generator.| + | | The trajectory generator projects a sample of possible trajectories the | + | | robot can follow from its current pose and velocity. These trajectories | + | | are then provided to the critics to score. | + | | | + | | You can create a custom trajectory generator by inheriting from the | + | | dwb_core::TrajectoryGenerator base class | + | | | + | | The trajectory generators provided with |PN| are: | + | | | + | | * dwb_plugins::StandardTrajectoryGenerator | + | | * dwb_plugins::LimitedAccelGenerator | + +----------------+----------------------------------------------------------------------------+ + +:critics: + +----------------+----------------------------------------------------------------------------+ + |**type** | vector<string> | + +----------------+----------------------------------------------------------------------------+ + |**default** | ["RotateToGoal", "Oscillation", "ObstacleFootprint", "GoalAlign", | + | | "PathAlign", "PathDist", "GoalDist"] | + +----------------+----------------------------------------------------------------------------+ + |**description** | This is a list of critic plugins that will evaluate the trajectories | + | | generated by the trajectory generator. Each critic evaluates the | + | | trajectories according to its own criteria. The scores from each critic | + | | will be combined, and the trajectory with the best score will be chosen. By| + | | weighting the different critics appropriately, the quality of the chosen | + | | trajectory can be modified. | + | | | + | | You can create a custom critic by inheriting from the | + | | dwb_core::TrajectoryCritic base class | + | | | + | | The critics provided with |PN| are: | + | | | + | | * dwb_critics::PreferForwardCritic | + | | * dwb_critics::GoalDistCritic | + | | * dwb_critics::PathAlignCritic | + | | * dwb_critics::GoalAlignCritic | + | | * dwb_critics::PathDistCritic | + | | * dwb_critics::OscillationCritic | + | | * dwb_critics::RotateToGoalCritic | + | | * dwb_critics::BaseObstacleCritic | + | | * dwb_critics::ObstacleFootprintCritic | + | | * dwb_critics::TwirlingCritic | + +----------------+----------------------------------------------------------------------------+ + +:goal_checker_name: + +----------------+----------------------------------------------------------------------------+ + |**type** | string | + +----------------+----------------------------------------------------------------------------+ + |**default** | "dwb_plugins::SimpleGoalChecker" | + +----------------+----------------------------------------------------------------------------+ + |**description** | This is the plugin that evaluates the current pose and velocity to | + | | determine if the goal has been reached | + | | | + | | You can create a custom goal checker by inheriting from the | + | | nav2_core::GoalChecker base class | + | | | + | | The critics provided with |PN| are: | + | | | + | | * dwb_plugins::SimpleGoalChecker | + | | * dwb_plugins::StoppedGoalChecker | + +----------------+----------------------------------------------------------------------------+ + +.. rst-class:: content-collapse + +Additional Parameters +********************* + +:prune_plan: + +----------------+----------------------------------------------------------------------------+ + |**type** | bool | + +----------------+----------------------------------------------------------------------------+ + |**default** | true | + +----------------+----------------------------------------------------------------------------+ + |**description** | If true, the path evaluated by the controller is trimmed to only include | + | | points within *prune_distance* of the current robot pose. This improves CPU| + | | performance, and also has the effect of making the Goal* critics aim for a | + | | more nearby goal | + +----------------+----------------------------------------------------------------------------+ + +:prune_distance: + +----------------+----------------------------------------------------------------------------+ + |**type** | double | + +----------------+----------------------------------------------------------------------------+ + |**default** | 1.0 | + +----------------+----------------------------------------------------------------------------+ + |**units** | m | + +----------------+----------------------------------------------------------------------------+ + |**description** | If *prune_plan* is true, all points in the path that are further away from | + | | the robot than this distance are discarded. | + | | This is re-evaluated each time the controller is run, so the points are not| + | | permanently discared. | + +----------------+----------------------------------------------------------------------------+ + +:transform_tolerance: + +----------------+----------------------------------------------------------------------------+ + |**type** | double | + +----------------+----------------------------------------------------------------------------+ + |**default** | 0.1 | + +----------------+----------------------------------------------------------------------------+ + |**units** | s | + +----------------+----------------------------------------------------------------------------+ + |**description** | When determining the current robot pose, if the transform data is older | + | | than this, an error is returned | + +----------------+----------------------------------------------------------------------------+ + +Debug Parameters +================ + +:debug_trajectory_details: + +----------------+----------------------------------------------------------------------------+ + |**type** | bool | + +----------------+----------------------------------------------------------------------------+ + |**default** | false | + +----------------+----------------------------------------------------------------------------+ + |**description** | If true and if all trajectories are rejected by the critics, DWB will print| + | | statistics on the console indicating which critics rejected the | + | | trajectories and for what reason. | + +----------------+----------------------------------------------------------------------------+ + +:publish_cost_grid_pc: + +----------------+----------------------------------------------------------------------------+ + |**type** | bool | + +----------------+----------------------------------------------------------------------------+ + |**default** | false | + +----------------+----------------------------------------------------------------------------+ + |**description** | Certain trajectory critics compute scores based on location in the costmap.| + | | For those critics, if this parameter is true, DWB will publish a PointCloud| + | | on the **cost_cloud** topic showing that critic's score for each cell. This| + | | can be visualized in RViz. | + | | | + | | The standard critics provided with |PN| that provide this capability are: | + | | | + | | * dwb_critics::GoalDistCritic | + | | * dwb_critics::PathAlignCritic | + | | * dwb_critics::GoalAlignCritic | + | | * dwb_critics::PathDistCritic | + | | * dwb_critics::BaseObstacleCritic | + | | * dwb_critics::ObstacleFootprintCritic | + +----------------+----------------------------------------------------------------------------+ + +:publish_evaluation: + +----------------+----------------------------------------------------------------------------+ + |**type** | bool | + +----------------+----------------------------------------------------------------------------+ + |**default** | true | + +----------------+----------------------------------------------------------------------------+ + |**description** | If true, publishes all evaluated trajectories and the scores each critic | + | | assigned them. This is the most detailed information on what is going on in| + | | DWB, but can be hard to visualize. The data is published on the | + | | **evaluation** topic | + +----------------+----------------------------------------------------------------------------+ + +:publish_global_plan: + +----------------+----------------------------------------------------------------------------+ + |**type** | bool | + +----------------+----------------------------------------------------------------------------+ + |**default** | true | + +----------------+----------------------------------------------------------------------------+ + |**description** | If true, publishes the path recieved by the controller. This is published | + | | on the **received_global_plan** topic and can be visualized in RViz | + +----------------+----------------------------------------------------------------------------+ + + +:publish_local_plan: + +----------------+----------------------------------------------------------------------------+ + |**type** | bool | + +----------------+----------------------------------------------------------------------------+ + |**default** | true | + +----------------+----------------------------------------------------------------------------+ + |**description** | If true, published the chosen trajectory on the **local_plan** topic. This | + | | can be visualized in RViz. | + +----------------+----------------------------------------------------------------------------+ + + +:publish_trajectories: + +----------------+----------------------------------------------------------------------------+ + |**type** | bool | + +----------------+----------------------------------------------------------------------------+ + |**default** | true | + +----------------+----------------------------------------------------------------------------+ + |**description** | If true, all evaluated trajectories are published on the **marker** topic. | + | | The trajectories can be visualized in RViz and are color coded. Black means| + | | a critic rejected that particular trajectory as invalid. The remaining | + | | trajectories are scaled from red to green, with the best trajectories being| + | | the most green and the worst being the most red. | + +----------------+----------------------------------------------------------------------------+ + + | | | + +:publish_transformed_plan: + +----------------+----------------------------------------------------------------------------+ + |**type** | bool | + +----------------+----------------------------------------------------------------------------+ + |**default** | true | + +----------------+----------------------------------------------------------------------------+ + |**description** | If true, publishes the received path after it has been transformed into the| + | | local frame of reference. This is published on the | + | | **transformed_global_plan** topic and can be visualized in RViz | + +----------------+----------------------------------------------------------------------------+ + + +DWB Plugins +=========== + +.. toctree:: + :maxdepth: 1 + + dwb-plugins/trajectory-generators.rst + dwb-plugins/trajectory-critics.rst + dwb-plugins/goal-checkers.rst diff --git a/sphinx_doc/howtos/configuration/dwb-plugins/goal-checkers.rst b/sphinx_doc/howtos/configuration/dwb-plugins/goal-checkers.rst new file mode 100644 index 0000000000000000000000000000000000000000..89e4ad88abd8c754833e9187aadf94a4d6df0cab --- /dev/null +++ b/sphinx_doc/howtos/configuration/dwb-plugins/goal-checkers.rst @@ -0,0 +1,22 @@ +.. _dwb_goal_checkers: + +Goal Checkers +############# + +.. warning:: + + The parameters below are not properly scoped. The exact parameter names are + likely to change in the near future + +Common Parameters +================= + +:xy_goal_tolerance: + +:yaw_goal_tolerance: + +Simple Goal Checker +=================== + +Stopped Goal Checker +==================== diff --git a/sphinx_doc/howtos/configuration/dwb-plugins/trajectory-critics.rst b/sphinx_doc/howtos/configuration/dwb-plugins/trajectory-critics.rst new file mode 100644 index 0000000000000000000000000000000000000000..d4d6c6b7d518cdaa37ab7e262ebd204bdb50271c --- /dev/null +++ b/sphinx_doc/howtos/configuration/dwb-plugins/trajectory-critics.rst @@ -0,0 +1,117 @@ +.. _dwb_trajectory_critics: + +Trajectory Critics +################## + +.. warning:: + + The parameters below are not properly scoped. The exact parameter names are + likely to change in the near future + +Base Obstacle +============= +:BaseObstacle.class: + +:BaseObstacle.scale: + +:BaseObstacle.sum_scores: + + +Goal Align +========== +:GoalAlign.aggregation_type: + +:GoalAlign.class: + +:GoalAlign.forward_point_distance: + +:GoalAlign.scale: + + +Goal Distance +============= +:GoalDist.aggregation_type: + +:GoalDist.class: + +:GoalDist.scale: + + +Oscillation +=========== +:Oscillation.class: + +:Oscillation.oscillation_reset_angle: + +:Oscillation.oscillation_reset_dist: + +:Oscillation.oscillation_reset_time: + +:Oscillation.scale: + +:Oscillation.x_only_threshold: + + +Obstacle Footprint +================== + +Path Align +========== + +Parameters +********** + +:PathAlign.forward_point_distance: + +:PathAlign.scale: + +.. rst-class:: content-collapse + +Additional Parameters +********************* + +:PathAlign.aggregation_type: + +:PathAlign.class: + + +Path Distance +============= + +Parameters +********** + +:PathDist.scale: + +.. rst-class:: content-collapse + +Additional Parameters +********************* + +:PathDist.aggregation_type: + +:PathDist.class: + +Prefer Forward +============== + +Rotate To Goal +============== + +Parameters +********** + +:RotateToGoal.scale: + +:RotateToGoal.xy_goal_tolerance: + +.. rst-class:: content-collapse + +Additional Parameters +********************* + +:RotateToGoal.class: + + +Twirling +======== diff --git a/sphinx_doc/howtos/configuration/dwb-plugins/trajectory-generators.rst b/sphinx_doc/howtos/configuration/dwb-plugins/trajectory-generators.rst new file mode 100644 index 0000000000000000000000000000000000000000..247624c4c089a93dcdfe2c38e64069814753026e --- /dev/null +++ b/sphinx_doc/howtos/configuration/dwb-plugins/trajectory-generators.rst @@ -0,0 +1,61 @@ +.. _dwb_trajectory_generators: + +Trajectory Generators +##################### + +.. warning:: + + The parameters below are not properly scoped. The exact parameter names are + likely to change in the near future + +Common Parameters +================= + +:acc_lim_theta: + +:acc_lim_x: + +:acc_lim_y: + +:decel_lim_theta: + +:decel_lim_x: + +:decel_lim_y: + +:max_speed_xy: + +:max_vel_theta: + +:max_vel_x: + +:max_vel_y: + +:min_speed_theta: + +:min_speed_xy: + +:min_theta_velocity_threshold: + +:min_vel_x: + +:min_vel_y: + +:min_x_velocity_threshold: + +:min_y_velocity_threshold: + +:vx_samples: + +:vy_samples: + +:discretize_by_time: + +:sim_time: + + +Standard Trajectory Generator +============================= + +Limited Acceleration Trajectory Generator +========================================= diff --git a/sphinx_doc/howtos/tunning/index.rst b/sphinx_doc/howtos/configuration/index.rst similarity index 64% rename from sphinx_doc/howtos/tunning/index.rst rename to sphinx_doc/howtos/configuration/index.rst index d06adebf825bf8f273d464dfba362aa80e39aba3..8a7837036dff8ed51591e0e0f26908d8e6ba1996 100644 --- a/sphinx_doc/howtos/tunning/index.rst +++ b/sphinx_doc/howtos/configuration/index.rst @@ -1,7 +1,7 @@ -.. _docs_tunning: +.. _docs_configuration: -Tunning Guidelines -################## +Configuration Guidelines +######################## This guide provides a process through which the user can adjust the tunable parameters to obtain the best navigation performance. @@ -9,4 +9,5 @@ the best navigation performance. .. toctree:: :maxdepth: 1 + configuring-the-controller.rst params/tunable-params.rst diff --git a/sphinx_doc/howtos/tunning/params/tunable-params.rst b/sphinx_doc/howtos/configuration/params/tunable-params.rst similarity index 100% rename from sphinx_doc/howtos/tunning/params/tunable-params.rst rename to sphinx_doc/howtos/configuration/params/tunable-params.rst diff --git a/sphinx_doc/howtos/index.rst b/sphinx_doc/howtos/index.rst index b69ccd03e6331965db28d9b945504bc750ace9b8..04ba3aace43fa77d37a285d98b3d3c3359d72a86 100644 --- a/sphinx_doc/howtos/index.rst +++ b/sphinx_doc/howtos/index.rst @@ -6,6 +6,7 @@ How-Tos .. toctree:: :maxdepth: 1 + build_instructions/index.rst tutorials/index.rst docs/index.rst - tunning/index.rst + configuration/index.rst